diff --git a/android/CMakeLists.txt b/android/CMakeLists.txt index b696d8de..be9c458b 100644 --- a/android/CMakeLists.txt +++ b/android/CMakeLists.txt @@ -133,6 +133,18 @@ set_target_properties(tbbmalloc_proxy PROPERTIES ) set(tbb_libs_name tbbmalloc_proxy tbbmalloc tbb) +if(USE_PHYSICS_PHYSX) + set(PhysXSDK PhysXCooking PhysXCharacterKinematic PhysXVehicle PhysXExtensions PhysX PhysXPvdSDK PhysXCommon PhysXFoundation) + foreach(PX IN LISTS PhysXSDK) + add_library(${PX} STATIC IMPORTED GLOBAL) + set_target_properties(${PX} PROPERTIES + IMPORTED_LOCATION ${platform_spec_path}/PhysX/lib${PX}_static.a + ) + endforeach() +else() + set(PhysXSDK) +endif() + list(APPEND CC_EXTERNAL_LIBS freetype jpeg @@ -144,6 +156,7 @@ list(APPEND CC_EXTERNAL_LIBS android_platform ${glslang_libs_name} ${tbb_libs_name} + ${PhysXSDK} ) diff --git a/android/arm64-v8a/PhysX/libPhysXCharacterKinematic_static.a b/android/arm64-v8a/PhysX/libPhysXCharacterKinematic_static.a new file mode 100644 index 00000000..a0bcba2e Binary files /dev/null and b/android/arm64-v8a/PhysX/libPhysXCharacterKinematic_static.a differ diff --git a/android/arm64-v8a/PhysX/libPhysXCommon_static.a b/android/arm64-v8a/PhysX/libPhysXCommon_static.a new file mode 100644 index 00000000..6312d32a Binary files /dev/null and b/android/arm64-v8a/PhysX/libPhysXCommon_static.a differ diff --git a/android/arm64-v8a/PhysX/libPhysXCooking_static.a b/android/arm64-v8a/PhysX/libPhysXCooking_static.a new file mode 100644 index 00000000..1f396a79 Binary files /dev/null and b/android/arm64-v8a/PhysX/libPhysXCooking_static.a differ diff --git a/android/arm64-v8a/PhysX/libPhysXExtensions_static.a b/android/arm64-v8a/PhysX/libPhysXExtensions_static.a new file mode 100644 index 00000000..1521bd2a Binary files /dev/null and b/android/arm64-v8a/PhysX/libPhysXExtensions_static.a differ diff --git a/android/arm64-v8a/PhysX/libPhysXFoundation_static.a b/android/arm64-v8a/PhysX/libPhysXFoundation_static.a new file mode 100644 index 00000000..cb86f53a Binary files /dev/null and b/android/arm64-v8a/PhysX/libPhysXFoundation_static.a differ diff --git a/android/arm64-v8a/PhysX/libPhysXPvdSDK_static.a b/android/arm64-v8a/PhysX/libPhysXPvdSDK_static.a new file mode 100644 index 00000000..f795f7d4 Binary files /dev/null and b/android/arm64-v8a/PhysX/libPhysXPvdSDK_static.a differ diff --git a/android/arm64-v8a/PhysX/libPhysXVehicle_static.a b/android/arm64-v8a/PhysX/libPhysXVehicle_static.a new file mode 100644 index 00000000..66f760bb Binary files /dev/null and b/android/arm64-v8a/PhysX/libPhysXVehicle_static.a differ diff --git a/android/arm64-v8a/PhysX/libPhysX_static.a b/android/arm64-v8a/PhysX/libPhysX_static.a new file mode 100644 index 00000000..b8f0d222 Binary files /dev/null and b/android/arm64-v8a/PhysX/libPhysX_static.a differ diff --git a/android/armeabi-v7a/PhysX/libPhysXCharacterKinematic_static.a b/android/armeabi-v7a/PhysX/libPhysXCharacterKinematic_static.a new file mode 100644 index 00000000..714c73b4 Binary files /dev/null and b/android/armeabi-v7a/PhysX/libPhysXCharacterKinematic_static.a differ diff --git a/android/armeabi-v7a/PhysX/libPhysXCommon_static.a b/android/armeabi-v7a/PhysX/libPhysXCommon_static.a new file mode 100644 index 00000000..a8fe3788 Binary files /dev/null and b/android/armeabi-v7a/PhysX/libPhysXCommon_static.a differ diff --git a/android/armeabi-v7a/PhysX/libPhysXCooking_static.a b/android/armeabi-v7a/PhysX/libPhysXCooking_static.a new file mode 100644 index 00000000..9cbb95fd Binary files /dev/null and b/android/armeabi-v7a/PhysX/libPhysXCooking_static.a differ diff --git a/android/armeabi-v7a/PhysX/libPhysXExtensions_static.a b/android/armeabi-v7a/PhysX/libPhysXExtensions_static.a new file mode 100644 index 00000000..b3dabcee Binary files /dev/null and b/android/armeabi-v7a/PhysX/libPhysXExtensions_static.a differ diff --git a/android/armeabi-v7a/PhysX/libPhysXFoundation_static.a b/android/armeabi-v7a/PhysX/libPhysXFoundation_static.a new file mode 100644 index 00000000..461f6357 Binary files /dev/null and b/android/armeabi-v7a/PhysX/libPhysXFoundation_static.a differ diff --git a/android/armeabi-v7a/PhysX/libPhysXPvdSDK_static.a b/android/armeabi-v7a/PhysX/libPhysXPvdSDK_static.a new file mode 100644 index 00000000..1368dbe3 Binary files /dev/null and b/android/armeabi-v7a/PhysX/libPhysXPvdSDK_static.a differ diff --git a/android/armeabi-v7a/PhysX/libPhysXVehicle_static.a b/android/armeabi-v7a/PhysX/libPhysXVehicle_static.a new file mode 100644 index 00000000..d4de7875 Binary files /dev/null and b/android/armeabi-v7a/PhysX/libPhysXVehicle_static.a differ diff --git a/android/armeabi-v7a/PhysX/libPhysX_static.a b/android/armeabi-v7a/PhysX/libPhysX_static.a new file mode 100644 index 00000000..962d0c99 Binary files /dev/null and b/android/armeabi-v7a/PhysX/libPhysX_static.a differ diff --git a/android/x86_64/PhysX/libPhysXCharacterKinematic_static.a b/android/x86_64/PhysX/libPhysXCharacterKinematic_static.a new file mode 100644 index 00000000..8674b7d0 Binary files /dev/null and b/android/x86_64/PhysX/libPhysXCharacterKinematic_static.a differ diff --git a/android/x86_64/PhysX/libPhysXCommon_static.a b/android/x86_64/PhysX/libPhysXCommon_static.a new file mode 100644 index 00000000..d5c633a1 Binary files /dev/null and b/android/x86_64/PhysX/libPhysXCommon_static.a differ diff --git a/android/x86_64/PhysX/libPhysXCooking_static.a b/android/x86_64/PhysX/libPhysXCooking_static.a new file mode 100644 index 00000000..14700a9e Binary files /dev/null and b/android/x86_64/PhysX/libPhysXCooking_static.a differ diff --git a/android/x86_64/PhysX/libPhysXExtensions_static.a b/android/x86_64/PhysX/libPhysXExtensions_static.a new file mode 100644 index 00000000..7c55d3e3 Binary files /dev/null and b/android/x86_64/PhysX/libPhysXExtensions_static.a differ diff --git a/android/x86_64/PhysX/libPhysXFoundation_static.a b/android/x86_64/PhysX/libPhysXFoundation_static.a new file mode 100644 index 00000000..30a229c9 Binary files /dev/null and b/android/x86_64/PhysX/libPhysXFoundation_static.a differ diff --git a/android/x86_64/PhysX/libPhysXPvdSDK_static.a b/android/x86_64/PhysX/libPhysXPvdSDK_static.a new file mode 100644 index 00000000..848368d7 Binary files /dev/null and b/android/x86_64/PhysX/libPhysXPvdSDK_static.a differ diff --git a/android/x86_64/PhysX/libPhysXVehicle_static.a b/android/x86_64/PhysX/libPhysXVehicle_static.a new file mode 100644 index 00000000..ae274b71 Binary files /dev/null and b/android/x86_64/PhysX/libPhysXVehicle_static.a differ diff --git a/android/x86_64/PhysX/libPhysX_static.a b/android/x86_64/PhysX/libPhysX_static.a new file mode 100644 index 00000000..5aa3c6c8 Binary files /dev/null and b/android/x86_64/PhysX/libPhysX_static.a differ diff --git a/ios/CMakeLists.txt b/ios/CMakeLists.txt index 7c114c61..81010298 100644 --- a/ios/CMakeLists.txt +++ b/ios/CMakeLists.txt @@ -144,6 +144,18 @@ set_target_properties(tbbmalloc_proxy PROPERTIES ) set(tbb_libs_name tbb tbbmalloc tbbmalloc_proxy) +if(USE_PHYSICS_PHYSX) + set(PhysXSDK PhysX PhysXCommon PhysXFoundation PhysXExtensions PhysXCooking PhysXCharacterKinematic PhysXVehicle PhysXPvdSDK) + foreach(PX IN LISTS PhysXSDK) + add_library(${PX} STATIC IMPORTED GLOBAL) + set_target_properties(${PX} PROPERTIES + IMPORTED_LOCATION ${CMAKE_CURRENT_LIST_DIR}/libs/PhysX/lib${PX}_static_64.a + ) + endforeach() +else() + set(PhysXSDK) +endif() + list(APPEND CC_EXTERNAL_INCLUDES ${CMAKE_CURRENT_LIST_DIR}/include ) @@ -159,4 +171,5 @@ list(APPEND CC_EXTERNAL_LIBS ${glslang_libs_name} ${spirv-cross_libs_name} ${tbb_libs_name} + ${PhysXSDK} ) diff --git a/ios/libs/PhysX/libPhysXCharacterKinematic_static_64.a b/ios/libs/PhysX/libPhysXCharacterKinematic_static_64.a new file mode 100644 index 00000000..d0dbb030 Binary files /dev/null and b/ios/libs/PhysX/libPhysXCharacterKinematic_static_64.a differ diff --git a/ios/libs/PhysX/libPhysXCommon_static_64.a b/ios/libs/PhysX/libPhysXCommon_static_64.a new file mode 100644 index 00000000..3ca061d6 Binary files /dev/null and b/ios/libs/PhysX/libPhysXCommon_static_64.a differ diff --git a/ios/libs/PhysX/libPhysXCooking_static_64.a b/ios/libs/PhysX/libPhysXCooking_static_64.a new file mode 100644 index 00000000..74c0694b Binary files /dev/null and b/ios/libs/PhysX/libPhysXCooking_static_64.a differ diff --git a/ios/libs/PhysX/libPhysXExtensions_static_64.a b/ios/libs/PhysX/libPhysXExtensions_static_64.a new file mode 100644 index 00000000..22d99426 Binary files /dev/null and b/ios/libs/PhysX/libPhysXExtensions_static_64.a differ diff --git a/ios/libs/PhysX/libPhysXFoundation_static_64.a b/ios/libs/PhysX/libPhysXFoundation_static_64.a new file mode 100644 index 00000000..dfea02c7 Binary files /dev/null and b/ios/libs/PhysX/libPhysXFoundation_static_64.a differ diff --git a/ios/libs/PhysX/libPhysXPvdSDK_static_64.a b/ios/libs/PhysX/libPhysXPvdSDK_static_64.a new file mode 100644 index 00000000..bd0faf03 Binary files /dev/null and b/ios/libs/PhysX/libPhysXPvdSDK_static_64.a differ diff --git a/ios/libs/PhysX/libPhysXVehicle_static_64.a b/ios/libs/PhysX/libPhysXVehicle_static_64.a new file mode 100644 index 00000000..fba488b3 Binary files /dev/null and b/ios/libs/PhysX/libPhysXVehicle_static_64.a differ diff --git a/ios/libs/PhysX/libPhysX_static_64.a b/ios/libs/PhysX/libPhysX_static_64.a new file mode 100644 index 00000000..a51bd27e Binary files /dev/null and b/ios/libs/PhysX/libPhysX_static_64.a differ diff --git a/mac/CMakeLists.txt b/mac/CMakeLists.txt index 88056fb4..b7911e1b 100644 --- a/mac/CMakeLists.txt +++ b/mac/CMakeLists.txt @@ -146,6 +146,18 @@ set_target_properties(tbbmalloc_proxy PROPERTIES ) set(tbb_libs_name tbb tbbmalloc tbbmalloc_proxy) +if(USE_PHYSICS_PHYSX) + set(PhysXSDK PhysX PhysXCommon PhysXFoundation PhysXExtensions PhysXCooking PhysXCharacterKinematic PhysXVehicle PhysXPvdSDK) + foreach(PX IN LISTS PhysXSDK) + add_library(${PX} STATIC IMPORTED GLOBAL) + set_target_properties(${PX} PROPERTIES + IMPORTED_LOCATION ${CMAKE_CURRENT_LIST_DIR}/libs/PhysX/lib${PX}_static_64.a + ) + endforeach() +else() + set(PhysXSDK) +endif() + list(APPEND CC_EXTERNAL_LIBS freetype jpeg @@ -159,6 +171,7 @@ list(APPEND CC_EXTERNAL_LIBS ${glslang_libs_name} ${spirv-cross_libs_name} ${tbb_libs_name} + ${PhysXSDK} ) list(APPEND CC_EXTERNAL_INCLUDES diff --git a/mac/libs/PhysX/libPhysXCharacterKinematic_static_64.a b/mac/libs/PhysX/libPhysXCharacterKinematic_static_64.a new file mode 100644 index 00000000..e0dffe60 Binary files /dev/null and b/mac/libs/PhysX/libPhysXCharacterKinematic_static_64.a differ diff --git a/mac/libs/PhysX/libPhysXCommon_static_64.a b/mac/libs/PhysX/libPhysXCommon_static_64.a new file mode 100644 index 00000000..fc6c1db0 Binary files /dev/null and b/mac/libs/PhysX/libPhysXCommon_static_64.a differ diff --git a/mac/libs/PhysX/libPhysXCooking_static_64.a b/mac/libs/PhysX/libPhysXCooking_static_64.a new file mode 100644 index 00000000..496a0565 Binary files /dev/null and b/mac/libs/PhysX/libPhysXCooking_static_64.a differ diff --git a/mac/libs/PhysX/libPhysXExtensions_static_64.a b/mac/libs/PhysX/libPhysXExtensions_static_64.a new file mode 100644 index 00000000..68957a15 Binary files /dev/null and b/mac/libs/PhysX/libPhysXExtensions_static_64.a differ diff --git a/mac/libs/PhysX/libPhysXFoundation_static_64.a b/mac/libs/PhysX/libPhysXFoundation_static_64.a new file mode 100644 index 00000000..a5d3ffa1 Binary files /dev/null and b/mac/libs/PhysX/libPhysXFoundation_static_64.a differ diff --git a/mac/libs/PhysX/libPhysXPvdSDK_static_64.a b/mac/libs/PhysX/libPhysXPvdSDK_static_64.a new file mode 100644 index 00000000..c86b5722 Binary files /dev/null and b/mac/libs/PhysX/libPhysXPvdSDK_static_64.a differ diff --git a/mac/libs/PhysX/libPhysXVehicle_static_64.a b/mac/libs/PhysX/libPhysXVehicle_static_64.a new file mode 100644 index 00000000..936587a9 Binary files /dev/null and b/mac/libs/PhysX/libPhysXVehicle_static_64.a differ diff --git a/mac/libs/PhysX/libPhysX_static_64.a b/mac/libs/PhysX/libPhysX_static_64.a new file mode 100644 index 00000000..64ec3f9e Binary files /dev/null and b/mac/libs/PhysX/libPhysX_static_64.a differ diff --git a/sources/CMakeLists.txt b/sources/CMakeLists.txt index 2f1c3f02..c6210f08 100644 --- a/sources/CMakeLists.txt +++ b/sources/CMakeLists.txt @@ -43,3 +43,16 @@ elseif(APPLE) include(${CMAKE_CURRENT_LIST_DIR}/SocketRocket/CMakeLists.txt) endif() endif() + +list(APPEND CC_EXTERNAL_INCLUDES + ${CMAKE_CURRENT_LIST_DIR} +) + +if(USE_PHYSICS_PHYSX) + list(APPEND CC_EXTERNAL_INCLUDES + ${CMAKE_CURRENT_LIST_DIR}/PhysX/PhysX/include + ${CMAKE_CURRENT_LIST_DIR}/PhysX/PhysX/source + ${CMAKE_CURRENT_LIST_DIR}/PhysX/PxShared/include + ) +endif() + diff --git a/sources/PhysX/PhysX/include/PxActor.h b/sources/PhysX/PhysX/include/PxActor.h new file mode 100644 index 00000000..0dfef1f8 --- /dev/null +++ b/sources/PhysX/PhysX/include/PxActor.h @@ -0,0 +1,330 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX_ACTOR +#define PX_PHYSICS_NX_ACTOR + +/** \addtogroup physics + @{ +*/ + +#include "PxPhysXConfig.h" +#include "foundation/PxBounds3.h" +#include "PxClient.h" +#include "common/PxBase.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxRigidActor; +class PxRigidBody; +class PxRigidStatic; +class PxRigidDynamic; +class PxArticulation; +class PxArticulationLink; + + +/** Group index which allows to specify 1- or 2-way interaction */ +typedef PxU8 PxDominanceGroup; // Must be < 32, PxU8. + +/** +\brief Flags which control the behavior of an actor. + +@see PxActorFlags PxActor PxActor.setActorFlag() PxActor.getActorFlags() +*/ +struct PxActorFlag +{ + enum Enum + { + /** + \brief Enable debug renderer for this actor + + @see PxScene.getRenderBuffer() PxRenderBuffer PxVisualizationParameter + */ + eVISUALIZATION = (1<<0), + + /** + \brief Disables scene gravity for this actor + */ + eDISABLE_GRAVITY = (1<<1), + + /** + \brief Enables the sending of PxSimulationEventCallback::onWake() and PxSimulationEventCallback::onSleep() notify events + + @see PxSimulationEventCallback::onWake() PxSimulationEventCallback::onSleep() + */ + eSEND_SLEEP_NOTIFIES = (1<<2), + + /** + \brief Disables simulation for the actor. + + \note This is only supported by PxRigidStatic and PxRigidDynamic actors and can be used to reduce the memory footprint when rigid actors are + used for scene queries only. + + \note Setting this flag will remove all constraints attached to the actor from the scene. + + \note If this flag is set, the following calls are forbidden: + \li PxRigidBody: setLinearVelocity(), setAngularVelocity(), addForce(), addTorque(), clearForce(), clearTorque() + \li PxRigidDynamic: setKinematicTarget(), setWakeCounter(), wakeUp(), putToSleep() + + \par Sleeping: + Raising this flag will set all velocities and the wake counter to 0, clear all forces, clear the kinematic target, put the actor + to sleep and wake up all touching actors from the previous frame. + */ + eDISABLE_SIMULATION = (1<<3) + }; +}; + +/** +\brief collection of set bits defined in PxActorFlag. + +@see PxActorFlag +*/ +typedef PxFlags PxActorFlags; +PX_FLAGS_OPERATORS(PxActorFlag::Enum,PxU8) + +/** +\brief Identifies each type of actor. +@see PxActor +*/ +struct PxActorType +{ + enum Enum + { + /** + \brief A static rigid body + @see PxRigidStatic + */ + eRIGID_STATIC, + + /** + \brief A dynamic rigid body + @see PxRigidDynamic + */ + eRIGID_DYNAMIC, + + /** + \brief An articulation link + @see PxArticulationLink + */ + eARTICULATION_LINK, + + //brief internal use only! + eACTOR_COUNT, + + eACTOR_FORCE_DWORD = 0x7fffffff + }; +}; + +/** +\brief PxActor is the base class for the main simulation objects in the physics SDK. + +The actor is owned by and contained in a PxScene. + +*/ +class PxActor : public PxBase +{ +public: + /** + \brief Deletes the actor. + + Do not keep a reference to the deleted instance. + + If the actor belongs to a #PxAggregate object, it is automatically removed from the aggregate. + + @see PxBase.release(), PxAggregate + */ + virtual void release() = 0; + + /** + \brief Retrieves the type of actor. + + \return The actor type of the actor. + + @see PxActorType + */ + virtual PxActorType::Enum getType() const = 0; + + /** + \brief Retrieves the scene which this actor belongs to. + + \return Owner Scene. NULL if not part of a scene. + + @see PxScene + */ + virtual PxScene* getScene() const = 0; + + // Runtime modifications + + /** + \brief Sets a name string for the object that can be retrieved with getName(). + + This is for debugging and is not used by the SDK. The string is not copied by the SDK, + only the pointer is stored. + + \param[in] name String to set the objects name to. + + Default: NULL + + @see getName() + */ + virtual void setName(const char* name) = 0; + + /** + \brief Retrieves the name string set with setName(). + + \return Name string associated with object. + + @see setName() + */ + virtual const char* getName() const = 0; + + /** + \brief Retrieves the axis aligned bounding box enclosing the actor. + + \param[in] inflation Scale factor for computed world bounds. Box extents are multiplied by this value. + + \return The actor's bounding box. + + @see PxBounds3 + */ + virtual PxBounds3 getWorldBounds(float inflation=1.01f) const = 0; + + /** + \brief Raises or clears a particular actor flag. + + See the list of flags #PxActorFlag + + Sleeping: Does NOT wake the actor up automatically. + + \param[in] flag The PxActor flag to raise(set) or clear. See #PxActorFlag. + \param[in] value The boolean value to assign to the flag. + + Default: PxActorFlag::eVISUALIZATION + + @see PxActorFlag getActorFlags() + */ + virtual void setActorFlag(PxActorFlag::Enum flag, bool value) = 0; + /** + \brief sets the actor flags + + See the list of flags #PxActorFlag + @see PxActorFlag setActorFlag() + */ + virtual void setActorFlags( PxActorFlags inFlags ) = 0; + + /** + \brief Reads the PxActor flags. + + See the list of flags #PxActorFlag + + \return The values of the PxActor flags. + + @see PxActorFlag setActorFlag() + */ + virtual PxActorFlags getActorFlags() const = 0; + + /** + \brief Assigns dynamic actors a dominance group identifier. + + PxDominanceGroup is a 5 bit group identifier (legal range from 0 to 31). + + The PxScene::setDominanceGroupPair() lets you set certain behaviors for pairs of dominance groups. + By default every dynamic actor is created in group 0. + + Default: 0 + + Sleeping: Changing the dominance group does NOT wake the actor up automatically. + + \param[in] dominanceGroup The dominance group identifier. Range: [0..31] + + @see getDominanceGroup() PxDominanceGroup PxScene::setDominanceGroupPair() + */ + virtual void setDominanceGroup(PxDominanceGroup dominanceGroup) = 0; + + /** + \brief Retrieves the value set with setDominanceGroup(). + + \return The dominance group of this actor. + + @see setDominanceGroup() PxDominanceGroup PxScene::setDominanceGroupPair() + */ + virtual PxDominanceGroup getDominanceGroup() const = 0; + + + /** + \brief Sets the owner client of an actor. + + This cannot be done once the actor has been placed into a scene. + + Default: PX_DEFAULT_CLIENT + + @see PxClientID PxScene::createClient() + */ + virtual void setOwnerClient( PxClientID inClient ) = 0; + + /** + \brief Returns the owner client that was specified with at creation time. + + This value cannot be changed once the object is placed into the scene. + + @see PxClientID PxScene::createClient() + */ + virtual PxClientID getOwnerClient() const = 0; + + /** + \brief Retrieves the aggregate the actor might be a part of. + + \return The aggregate the actor is a part of, or NULL if the actor does not belong to an aggregate. + + @see PxAggregate + */ + virtual PxAggregate* getAggregate() const = 0; + + //public variables: + void* userData; //!< user can assign this to whatever, usually to create a 1:1 relationship with a user object. + +protected: + PX_INLINE PxActor(PxType concreteType, PxBaseFlags baseFlags) : PxBase(concreteType, baseFlags), userData(NULL) {} + PX_INLINE PxActor(PxBaseFlags baseFlags) : PxBase(baseFlags) {} + virtual ~PxActor() {} + virtual bool isKindOf(const char* name) const { return !::strcmp("PxActor", name) || PxBase::isKindOf(name); } + + +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/PxAggregate.h b/sources/PhysX/PhysX/include/PxAggregate.h new file mode 100644 index 00000000..f794de22 --- /dev/null +++ b/sources/PhysX/PhysX/include/PxAggregate.h @@ -0,0 +1,213 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX_AGGREGATE +#define PX_PHYSICS_NX_AGGREGATE + +/** \addtogroup physics +@{ +*/ + +#include "PxPhysXConfig.h" +#include "common/PxBase.h" + + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxActor; +class PxBVHStructure; + +/** +\brief Class to aggregate actors into a single broad-phase entry. + +A PxAggregate object is a collection of PxActors, which will exist as a single entry in the +broad-phase structures. This has 3 main benefits: + +1) it reduces "broad phase pollution" by allowing a collection of spatially coherent broad-phase +entries to be replaced by a single aggregated entry (e.g. a ragdoll or a single actor with a +large number of attached shapes). + +2) it reduces broad-phase memory usage + +3) filtering can be optimized a lot if self-collisions within an aggregate are not needed. For + example if you don't need collisions between ragdoll bones, it's faster to simply disable + filtering once and for all, for the aggregate containing the ragdoll, rather than filtering + out each bone-bone collision in the filter shader. + +@see PxActor, PxPhysics.createAggregate +*/ + +class PxAggregate : public PxBase +{ +public: + + /** + \brief Deletes the aggregate object. + + Deleting the PxAggregate object does not delete the aggregated actors. If the PxAggregate object + belongs to a scene, the aggregated actors are automatically re-inserted in that scene. If you intend + to delete both the PxAggregate and its actors, it is best to release the actors first, then release + the PxAggregate when it is empty. + */ + virtual void release() = 0; + + /** + \brief Adds an actor to the aggregate object. + + A warning is output if the total number of actors is reached, or if the incoming actor already belongs + to an aggregate. + + If the aggregate belongs to a scene, adding an actor to the aggregate also adds the actor to that scene. + + If the actor already belongs to a scene, a warning is output and the call is ignored. You need to remove + the actor from the scene first, before adding it to the aggregate. + + \note When BVHStructure is provided the actor shapes are grouped together. + The scene query pruning structure inside PhysX SDK will store/update one + bound per actor. The scene queries against such an actor will query actor + bounds and then make a local space query against the provided BVH structure, which is in + actor's local space. + + \param [in] actor The actor that should be added to the aggregate + \param [in] bvhStructure BVHStructure for actor shapes. + return true if success + */ + virtual bool addActor(PxActor& actor, const PxBVHStructure* bvhStructure = NULL) = 0; + + /** + \brief Removes an actor from the aggregate object. + + A warning is output if the incoming actor does not belong to the aggregate. Otherwise the actor is + removed from the aggregate. If the aggregate belongs to a scene, the actor is reinserted in that + scene. If you intend to delete the actor, it is best to call #PxActor::release() directly. That way + the actor will be automatically removed from its aggregate (if any) and not reinserted in a scene. + + \param [in] actor The actor that should be removed from the aggregate + return true if success + */ + virtual bool removeActor(PxActor& actor) = 0; + + /** + \brief Adds an articulation to the aggregate object. + + A warning is output if the total number of actors is reached (every articulation link counts as an actor), + or if the incoming articulation already belongs to an aggregate. + + If the aggregate belongs to a scene, adding an articulation to the aggregate also adds the articulation to that scene. + + If the articulation already belongs to a scene, a warning is output and the call is ignored. You need to remove + the articulation from the scene first, before adding it to the aggregate. + + \param [in] articulation The articulation that should be added to the aggregate + return true if success + */ + virtual bool addArticulation(PxArticulationBase& articulation) = 0; + + /** + \brief Removes an articulation from the aggregate object. + + A warning is output if the incoming articulation does not belong to the aggregate. Otherwise the articulation is + removed from the aggregate. If the aggregate belongs to a scene, the articulation is reinserted in that + scene. If you intend to delete the articulation, it is best to call #PxArticulation::release() directly. That way + the articulation will be automatically removed from its aggregate (if any) and not reinserted in a scene. + + \param [in] articulation The articulation that should be removed from the aggregate + return true if success + */ + virtual bool removeArticulation(PxArticulationBase& articulation) = 0; + + /** + \brief Returns the number of actors contained in the aggregate. + + You can use #getActors() to retrieve the actor pointers. + + \return Number of actors contained in the aggregate. + + @see PxActor getActors() + */ + virtual PxU32 getNbActors() const = 0; + + /** + \brief Retrieves max amount of actors that can be contained in the aggregate. + + \return Max aggregate size. + + @see PxPhysics::createAggregate() + */ + virtual PxU32 getMaxNbActors() const = 0; + + /** + \brief Retrieve all actors contained in the aggregate. + + You can retrieve the number of actor pointers by calling #getNbActors() + + \param[out] userBuffer The buffer to store the actor pointers. + \param[in] bufferSize Size of provided user buffer. + \param[in] startIndex Index of first actor pointer to be retrieved + \return Number of actor pointers written to the buffer. + + @see PxShape getNbShapes() + */ + virtual PxU32 getActors(PxActor** userBuffer, PxU32 bufferSize, PxU32 startIndex=0) const = 0; + + /** + \brief Retrieves the scene which this aggregate belongs to. + + \return Owner Scene. NULL if not part of a scene. + + @see PxScene + */ + virtual PxScene* getScene() = 0; + + /** + \brief Retrieves aggregate's self-collision flag. + + \return self-collision flag + */ + virtual bool getSelfCollision() const = 0; + + virtual const char* getConcreteTypeName() const { return "PxAggregate"; } + +protected: + PX_INLINE PxAggregate(PxType concreteType, PxBaseFlags baseFlags) : PxBase(concreteType, baseFlags) {} + PX_INLINE PxAggregate(PxBaseFlags baseFlags) : PxBase(baseFlags) {} + virtual ~PxAggregate() {} + virtual bool isKindOf(const char* name) const { return !::strcmp("PxAggregate", name) || PxBase::isKindOf(name); } +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/PxArticulation.h b/sources/PhysX/PhysX/include/PxArticulation.h new file mode 100644 index 00000000..4cd51ce5 --- /dev/null +++ b/sources/PhysX/PhysX/include/PxArticulation.h @@ -0,0 +1,281 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX_ARTICULATION +#define PX_PHYSICS_NX_ARTICULATION +/** \addtogroup physics +@{ */ + +#include "PxArticulationBase.h" + + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxArticulationLink; + +/** +\brief Articulation drive cache + +This cache is used for making one or more impulse applications to the articulation. + +@see PxArticulation PxArticulation.createDriveCache +*/ +class PxArticulationDriveCache +{ +protected: + PxArticulationDriveCache(); +}; + + +/** +\brief a tree structure of bodies connected by joints that is treated as a unit by the dynamics solver + +Articulations are more expensive to simulate than the equivalent collection of +PxRigidDynamic and PxJoint structures, but because the dynamics solver treats +each articulation as a single object, they are much less prone to separation and +have better support for actuation. An articulation may have at most 64 links. + +@see PxArticulationJoint PxArticulationLink PxPhysics.createArticulation +*/ + +#if PX_VC +#pragma warning(push) +#pragma warning(disable : 4435) +#endif + +class PxArticulation : public PxArticulationBase +{ +public: + + virtual void release() = 0; + + /** + \brief sets maxProjectionIterations. + + This is the maximum number of iterations to run projection on the articulation to bring + the links back together if the separation tolerance is exceeded. + + + \param[in] iterations the maximum number of projection iterations + Default: 4 + + @see getMaxProjectionIterations() + */ + virtual void setMaxProjectionIterations(PxU32 iterations) = 0; + + /** + \brief gets maxProjectionIterations. + + \return the maximum number of projection iterations + + @see setMaxProjectionIterations() + */ + + virtual PxU32 getMaxProjectionIterations() const = 0; + + /** + \brief sets separationTolerance. + + This is the maximum allowed separation of any joint in the articulation before projection is used + + Default: 0.1f, scaled by the tolerance scale + + \param[in] tolerance the separation tolerance for the articulation + + @see getSeparationTolerance() + */ + virtual void setSeparationTolerance(PxReal tolerance) = 0; + + /** + \brief gets separationTolerance. + + \return the separation tolerance + + @see setSeparationTolerance() + */ + + virtual PxReal getSeparationTolerance() const = 0; + + + /** + \brief sets the number of iterations used to compute the drive response to internal forces + + The drive model uses an iterative algorithm to determine the load on each joint of the articulation. + This is the number of iterations to use when computing response of the drive to internal forces. + + \param[in] iterations the number of iterations used to compute the drive response to internal forces. + + Default: 4 + + @see getInternalDriveIterations() + */ + virtual void setInternalDriveIterations(PxU32 iterations) = 0; + + /** + \brief gets internal driveIterations. + + \return the number of iterations used to compute the drive response to internal forces + + @see setInternalDriveIterations() + */ + + virtual PxU32 getInternalDriveIterations() const = 0; + + + /** + \brief sets the number of iterations for drive response to external forces. + + The drive model uses an iterative algorithm to determine the load on each joint of the articulation. + This is the number of iterations to use when computing response of the drive to external forces. + + \param[in] iterations the number of iterations used to compute the drive response to external forces. + + Default: 4 + + @see getExternalDriveIterations() + */ + + virtual void setExternalDriveIterations(PxU32 iterations) = 0; + + /** + \brief gets externalDriveIterations. + + \return the number of iterations used to compute the drive response to external forces + + @see setExternalDriveIterations() + */ + + virtual PxU32 getExternalDriveIterations() const = 0; + + /** + \brief create a drive cache for applying impulses which are propagated to the entire articulation + + \param[in] compliance the compliance value to use at all joints of the articulation. This is equivalent to the external compliance + parameter for articulation joints, as the impulse is treated as an external force + \param[in] driveIterations the number of iterations to use to evaluate the drive strengths + + \return a drive cache + + @see PxArticulationDriveCache updateDriveCache releaseDriveCache applyImpulse computeImpulseResponse + + \note this call may only be made on articulations that are in a scene, and may not be made during simulation + + */ + virtual PxArticulationDriveCache* + createDriveCache(PxReal compliance, PxU32 driveIterations) const = 0; + + + /** + \brief update a drive cache + + \param[in] driveCache the drive cache to update + \param[in] compliance the compliance value to use at all joints of the articulation. + \param[in] driveIterations the number of iterations to use to evaluate the drive strengths + + @see releaseDriveCache createDriveCache applyImpulse computeImpulseResponse + + \note this call may only be made on articulations that are in a scene, and may not be made during simulation + + */ + virtual void updateDriveCache(PxArticulationDriveCache& driveCache, + PxReal compliance, + PxU32 driveIterations) const = 0; + + /** + \brief release a drive cache + + \param[in] driveCache the drive cache to release + + @see createDriveCache updateDriveCache + */ + virtual void releaseDriveCache(PxArticulationDriveCache& driveCache) const = 0; + + /** + \brief apply an impulse to an entire articulation + + \param[in] link the link to which to apply the impulse + \param[in] driveCache the drive cache + \param[in] linearImpulse the linear impulse to apply + \param[in] angularImpulse the angular impulse to apply + + @see computeImpulseResponse + + \note this call may only be made on articulations that are in a scene, and may not be made during simulation + + */ + virtual void applyImpulse(PxArticulationLink* link, + const PxArticulationDriveCache& driveCache, + const PxVec3& linearImpulse, + const PxVec3& angularImpulse) = 0; + + /** + \brief determine the effect of applying an impulse to an entire articulation, without applying the impulse + + \param[in] link the link to which to apply the impulse + \param[out] linearResponse the change in linear velocity of the articulation link + \param[out] angularResponse the change in angular velocity of the articulation link + \param[in] driveCache the drive cache + \param[in] linearImpulse the linear impulse to apply + \param[in] angularImpulse the angular impulse to apply + + @see applyImpulse + + This call will wake up the articulation if it is asleep. + + \note this call may only be made on articulations that are in a scene, and may not be made during simulation + */ + + virtual void computeImpulseResponse(PxArticulationLink*link, + PxVec3& linearResponse, + PxVec3& angularResponse, + const PxArticulationDriveCache& driveCache, + const PxVec3& linearImpulse, + const PxVec3& angularImpulse) const = 0; + +protected: + PX_INLINE PxArticulation(PxType concreteType, PxBaseFlags baseFlags) : PxArticulationBase(concreteType, baseFlags){} + PX_INLINE PxArticulation(PxBaseFlags baseFlags) : PxArticulationBase(baseFlags){} + virtual ~PxArticulation() {} + +}; + +#if PX_VC +#pragma warning(pop) +#endif + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/PxArticulationBase.h b/sources/PhysX/PhysX/include/PxArticulationBase.h new file mode 100644 index 00000000..66237fdb --- /dev/null +++ b/sources/PhysX/PhysX/include/PxArticulationBase.h @@ -0,0 +1,320 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX_ARTICULATION_BASE +#define PX_PHYSICS_NX_ARTICULATION_BASE +/** \addtogroup physics +@{ */ + +#include "PxPhysXConfig.h" +#include "common/PxBase.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + + class PxArticulationImpl; + + /** + \brief a tree structure of bodies connected by joints that is treated as a unit by the dynamics solver + + Articulations are more expensive to simulate than the equivalent collection of + PxRigidDynamic and PxJoint structures, but because the dynamics solver treats + each articulation as a single object, they are much less prone to separation and + have better support for actuation. An articulation may have at most 64 links. + + @see PxArticulationJoint PxArticulationLink PxPhysics.createArticulation + */ + class PxArticulationBase : public PxBase + { + public: + + /** + \brief Retrieves the scene which this articulation belongs to. + + \return Owner Scene. NULL if not part of a scene. + + @see PxScene + */ + virtual PxScene* getScene() const = 0; + + /** + \brief Sets the solver iteration counts for the articulation. + + The solver iteration count determines how accurately joints and contacts are resolved. + If you are having trouble with jointed bodies oscillating and behaving erratically, then + setting a higher position iteration count may improve their stability. + + If intersecting bodies are being depenetrated too violently, increase the number of velocity + iterations. More velocity iterations will drive the relative exit velocity of the intersecting + objects closer to the correct value given the restitution. + + \param[in] minPositionIters Number of position iterations the solver should perform for this articulation. Range: [1,255] + \param[in] minVelocityIters Number of velocity iterations the solver should perform for this articulation. Range: [1,255] + + @see getSolverIterationCounts() + */ + virtual void setSolverIterationCounts(PxU32 minPositionIters, PxU32 minVelocityIters = 1) = 0; + + /** + \brief Retrieves the solver iteration counts. + + @see setSolverIterationCounts() + */ + virtual void getSolverIterationCounts(PxU32 & minPositionIters, PxU32 & minVelocityIters) const = 0; + + /** + \brief Returns true if this articulation is sleeping. + + When an actor does not move for a period of time, it is no longer simulated in order to save time. This state + is called sleeping. However, because the object automatically wakes up when it is either touched by an awake object, + or a sleep-affecting property is changed by the user, the entire sleep mechanism should be transparent to the user. + + An articulation can only go to sleep if all links are ready for sleeping. An articulation is guaranteed to be awake + if at least one of the following holds: + + \li The wake counter is positive (see #setWakeCounter()). + \li The linear or angular velocity of any link is non-zero. + \li A non-zero force or torque has been applied to the articulation or any of its links. + + If an articulation is sleeping, the following state is guaranteed: + + \li The wake counter is zero. + \li The linear and angular velocity of all links is zero. + \li There is no force update pending. + + When an articulation gets inserted into a scene, it will be considered asleep if all the points above hold, else it will + be treated as awake. + + If an articulation is asleep after the call to PxScene::fetchResults() returns, it is guaranteed that the poses of the + links were not changed. You can use this information to avoid updating the transforms of associated of dependent objects. + + \note It is invalid to use this method if the articulation has not been added to a scene already. + + \return True if the articulation is sleeping. + + @see isSleeping() wakeUp() putToSleep() getSleepThreshold() + */ + virtual bool isSleeping() const = 0; + + /** + \brief Sets the mass-normalized energy threshold below which an articulation may go to sleep. + + The articulation will sleep if the energy of each body is below this threshold. + + \param[in] threshold Energy below which an actor may go to sleep. Range: [0, PX_MAX_F32) + + @see isSleeping() getSleepThreshold() wakeUp() putToSleep() + */ + virtual void setSleepThreshold(PxReal threshold) = 0; + + /** + \brief Returns the mass-normalized energy below which an articulation may go to sleep. + + \return The energy threshold for sleeping. + + @see isSleeping() wakeUp() putToSleep() setSleepThreshold() + */ + virtual PxReal getSleepThreshold() const = 0; + + /** + \brief Sets the mass-normalized kinetic energy threshold below which an articulation may participate in stabilization. + + Articulation whose kinetic energy divided by their mass is above this threshold will not participate in stabilization. + + This value has no effect if PxSceneFlag::eENABLE_STABILIZATION was not enabled on the PxSceneDesc. + + Default: 0.01 * PxTolerancesScale::speed * PxTolerancesScale::speed + + \param[in] threshold Energy below which an actor may participate in stabilization. Range: [0,inf) + + @see getStabilizationThreshold() PxSceneFlag::eENABLE_STABILIZATION + */ + virtual void setStabilizationThreshold(PxReal threshold) = 0; + + /** + \brief Returns the mass-normalized kinetic energy below which an articulation may participate in stabilization. + + Articulations whose kinetic energy divided by their mass is above this threshold will not participate in stabilization. + + \return The energy threshold for participating in stabilization. + + @see setStabilizationThreshold() PxSceneFlag::eENABLE_STABILIZATION + */ + virtual PxReal getStabilizationThreshold() const = 0; + + /** + \brief Sets the wake counter for the articulation. + + The wake counter value determines the minimum amount of time until the articulation can be put to sleep. Please note + that an articulation will not be put to sleep if the energy is above the specified threshold (see #setSleepThreshold()) + or if other awake objects are touching it. + + \note Passing in a positive value will wake the articulation up automatically. + + Default: 0.4 (which corresponds to 20 frames for a time step of 0.02) + + \param[in] wakeCounterValue Wake counter value. Range: [0, PX_MAX_F32) + + @see isSleeping() getWakeCounter() + */ + virtual void setWakeCounter(PxReal wakeCounterValue) = 0; + + /** + \brief Returns the wake counter of the articulation. + + \return The wake counter of the articulation. + + @see isSleeping() setWakeCounter() + */ + virtual PxReal getWakeCounter() const = 0; + + /** + \brief Wakes up the articulation if it is sleeping. + + The articulation will get woken up and might cause other touching objects to wake up as well during the next simulation step. + + \note This will set the wake counter of the articulation to the value specified in #PxSceneDesc::wakeCounterResetValue. + + \note It is invalid to use this method if the articulation has not been added to a scene already. + + @see isSleeping() putToSleep() + */ + virtual void wakeUp() = 0; + + /** + \brief Forces the articulation to sleep. + + The articulation will stay asleep during the next simulation step if not touched by another non-sleeping actor. + + \note This will set any applied force, the velocity and the wake counter of all bodies in the articulation to zero. + + \note It is invalid to use this method if the articulation has not been added to a scene already. + + @see isSleeping() wakeUp() + */ + virtual void putToSleep() = 0; + + /** + \brief adds a link to the articulation with default attribute values. + + \param[in] parent the parent link of the articulation. Should be NULL if (and only if) this is the root link + \param[in] pose the initial pose of the new link. Must be a valid transform + + \return the new link, or NULL if the link cannot be created because the articulation has reached + its maximum link count (currently 64). + + @see PxArticulationLink + */ + virtual PxArticulationLink* createLink(PxArticulationLink* parent, const PxTransform& pose) = 0; + + /** + \brief returns the number of links in the articulation + */ + virtual PxU32 getNbLinks() const = 0; + + /** + \brief returns the set of links in the articulation + + \param[in] userBuffer buffer into which to write an array of articulation link pointers + \param[in] bufferSize the size of the buffer. If this is not large enough to contain all the pointers to links, + only as many as will fit are written. + \param[in] startIndex Index of first link pointer to be retrieved + + \return the number of links written into the buffer. + + @see ArticulationLink + */ + virtual PxU32 getLinks(PxArticulationLink** userBuffer, PxU32 bufferSize, PxU32 startIndex = 0) const = 0; + + /** + \brief Sets a name string for the object that can be retrieved with getName(). + + This is for debugging and is not used by the SDK. The string is not copied by the SDK, + only the pointer is stored. + + \param[in] name String to set the objects name to. + + @see getName() + */ + virtual void setName(const char* name) = 0; + + /** + \brief Retrieves the name string set with setName(). + + \return Name string associated with object. + + @see setName() + */ + virtual const char* getName() const = 0; + + /** + \brief Retrieves the axis aligned bounding box enclosing the articulation. + + \param[in] inflation Scale factor for computed world bounds. Box extents are multiplied by this value. + + \return The articulation's bounding box. + + @see PxBounds3 + */ + virtual PxBounds3 getWorldBounds(float inflation = 1.01f) const = 0; + + /** + \brief Retrieves the aggregate the articulation might be a part of. + + \return The aggregate the articulation is a part of, or NULL if the articulation does not belong to an aggregate. + + @see PxAggregate + */ + virtual PxAggregate* getAggregate() const = 0; + + virtual PxArticulationImpl* getImpl() = 0; + virtual const PxArticulationImpl* getImpl() const = 0; + + void* userData; //!< user can assign this to whatever, usually to create a 1:1 relationship with a user object. + + virtual ~PxArticulationBase() {} + + protected: + PX_INLINE PxArticulationBase(PxType concreteType, PxBaseFlags baseFlags) : PxBase(concreteType, baseFlags), userData(NULL) {} + PX_INLINE PxArticulationBase(PxBaseFlags baseFlags) : PxBase(baseFlags) {} + + public: + virtual PxArticulationJointBase* createArticulationJoint(PxArticulationLink& parent, const PxTransform& parentFrame, PxArticulationLink& child, const PxTransform& childFrame) = 0; + virtual void releaseArticulationJoint(PxArticulationJointBase* joint) = 0; + }; + +#if !PX_DOXYGEN +} // namespace physx +#endif + + /** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/PxArticulationJoint.h b/sources/PhysX/PhysX/include/PxArticulationJoint.h new file mode 100644 index 00000000..4f503132 --- /dev/null +++ b/sources/PhysX/PhysX/include/PxArticulationJoint.h @@ -0,0 +1,495 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX_ARTICULATION_JOINT +#define PX_PHYSICS_NX_ARTICULATION_JOINT +/** \addtogroup physics +@{ */ + +#include "PxPhysXConfig.h" +#include "common/PxBase.h" +#include "solver/PxSolverDefs.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxArticulationJointImpl; + +/** +\brief The type of joint drive to use for the articulation joint. + +Two drive models are currently supported. in the TARGET model, the drive spring displacement will be determined +as the rotation vector from the relative quaternion beetween child and parent, and the target quaternion. + +In the ERROR model, the drive spring displacement will be taken directly from the imaginary part of the relative +quaternion. This drive model requires more computation on the part of the application, but allows driving the joint +with a spring displacement that is more than a complete rotation. + +@see PxArticulationJoint +*/ + +struct PxArticulationJointDriveType +{ + enum Enum + { + eTARGET = 0, // use the quaternion as the drive target + eERROR = 1 // use the vector part of the quaternion as the drive error. + }; +}; + +class PxArticulationJointBase : public PxBase +{ +public: + /** + \brief get the parent articulation link to which this articulation joint belongs + + \return the articulation link to which this joint belongs + */ + virtual PxArticulationLink& getParentArticulationLink() const = 0; + + /** + \brief set the joint pose in the parent frame + + \param[in] pose the joint pose in the parent frame + Default: the identity matrix + + @see getParentPose() + */ + virtual void setParentPose(const PxTransform& pose) = 0; + + /** + \brief get the joint pose in the parent frame + + \return the joint pose in the parent frame + + @see setParentPose() + */ + virtual PxTransform getParentPose() const = 0; + + /** + \brief get the child articulation link to which this articulation joint belongs + + \return the articulation link to which this joint belongs + */ + virtual PxArticulationLink& getChildArticulationLink() const = 0; + + /** + \brief set the joint pose in the child frame + + \param[in] pose the joint pose in the child frame + Default: the identity matrix + + @see getChildPose() + */ + virtual void setChildPose(const PxTransform& pose) = 0; + + /** + \brief get the joint pose in the child frame + + \return the joint pose in the child frame + + @see setChildPose() + */ + virtual PxTransform getChildPose() const = 0; + + virtual PxArticulationJointImpl* getImpl() = 0; + virtual const PxArticulationJointImpl* getImpl() const = 0; + + virtual ~PxArticulationJointBase() {} + +private: +protected: + PX_INLINE PxArticulationJointBase(PxType concreteType, PxBaseFlags baseFlags) : PxBase(concreteType, baseFlags) {} + PX_INLINE PxArticulationJointBase(PxBaseFlags baseFlags) : PxBase(baseFlags) {} + + virtual bool isKindOf(const char* name) const { return !::strcmp("PxArticulationJointBase", name) || PxBase::isKindOf(name); } +}; + + + +/** +\brief a joint between two links in an articulation. + +The joint model is very similar to a PxSphericalJoint with swing and twist limits, +and an implicit drive model. + +@see PxArticulation PxArticulationLink +*/ + +class PxArticulationJoint : public PxArticulationJointBase +{ +public: + + /** + \brief set the target drive + + This is the target position for the joint drive, measured in the parent constraint frame. + + \param[in] orientation the target orientation for the joint + Range: a unit quaternion + Default: the identity quaternion + + @see getTargetOrientation() + */ + virtual void setTargetOrientation(const PxQuat& orientation) = 0; + + /** + \brief get the target drive position + + \return the joint drive target position + + @see setTargetOrientation() + */ + virtual PxQuat getTargetOrientation() const = 0; + + /** + \brief set the target drive velocity + + This is the target velocity for the joint drive, measured in the parent constraint frame + + \param[in] velocity the target velocity for the joint + Default: the zero vector + + @see getTargetVelocity() + */ + virtual void setTargetVelocity(const PxVec3& velocity) = 0; + + /** + \brief get the target drive velocity + + \return the target velocity for the joint + + @see setTargetVelocity() + */ + virtual PxVec3 getTargetVelocity() const = 0; + + /** + \brief set the drive type + + \param[in] driveType the drive type for the joint + Default: PxArticulationJointDriveType::eTARGET + + @see getDriveType() + */ + virtual void setDriveType(PxArticulationJointDriveType::Enum driveType) = 0; + + /** + \brief get the drive type + + \return the drive type + + @see setDriveType() + */ + virtual PxArticulationJointDriveType::Enum getDriveType() const = 0; + + /** + \brief set the drive strength of the joint acceleration spring. + + The acceleration generated by the spring drive is proportional to + this value and the angle between the drive target position and the + current position. + + \param[in] spring the spring strength of the joint + Range: [0, PX_MAX_F32)
+ Default: 0.0 + + @see getStiffness() + */ + virtual void setStiffness(PxReal spring) = 0; + + /** + \brief get the drive strength of the joint acceleration spring + + \return the spring strength of the joint + + @see setStiffness() + */ + virtual PxReal getStiffness() const = 0; + + /** + \brief set the damping of the joint acceleration spring + + The acceleration generated by the spring drive is proportional to + this value and the difference between the angular velocity of the + joint and the target drive velocity. + + \param[in] damping the damping of the joint drive + Range: [0, PX_MAX_F32)
+ Default: 0.0 + + @see getDamping() + */ + virtual void setDamping(PxReal damping) = 0; + + /** + \brief get the damping of the joint acceleration spring + + @see setDamping() + */ + virtual PxReal getDamping() const = 0; + + /** + \brief set the internal compliance + + Compliance determines the extent to which the joint resists acceleration. + + There are separate values for resistance to accelerations caused by external + forces such as gravity and contact forces, and internal forces generated from + other joints. + + A low compliance means that forces have little effect, a compliance of 1 means + the joint does not resist such forces at all. + + \param[in] compliance the compliance to internal forces + Range: (0, 1] + Default: 0.0 + + @see getInternalCompliance() + */ + virtual void setInternalCompliance(PxReal compliance) = 0; + + /** + \brief get the internal compliance + + \return the compliance to internal forces + + @see setInternalCompliance() + */ + virtual PxReal getInternalCompliance() const = 0; + + /** + \brief get the drive external compliance + + Compliance determines the extent to which the joint resists acceleration. + + There are separate values for resistance to accelerations caused by external + forces such as gravity and contact forces, and internal forces generated from + other joints. + + A low compliance means that forces have little effect, a compliance of 1 means + the joint does not resist such forces at all. + + \param[in] compliance the compliance to external forces + Range: (0, 1] + Default: 0.0 + + @see getExternalCompliance() + */ + virtual void setExternalCompliance(PxReal compliance) = 0; + + /** + \brief get the drive external compliance + + \return the compliance to external forces + + @see setExternalCompliance() + */ + virtual PxReal getExternalCompliance() const = 0; + + /** + \brief set the extents of the cone limit. The extents are measured in the frame + of the parent. + + Note that very small or highly elliptical limit cones may result in jitter. + + \param[in] zLimit the allowed extent of rotation around the z-axis + \param[in] yLimit the allowed extent of rotation around the y-axis + Range: ( (0, Pi), (0, Pi) ) + Default: (Pi/4, Pi/4) + + \note Please note the order of zLimit and yLimit. + */ + virtual void setSwingLimit(PxReal zLimit, PxReal yLimit) = 0; + + /** + \brief get the extents for the swing limit cone + + \param[out] zLimit the allowed extent of rotation around the z-axis + \param[out] yLimit the allowed extent of rotation around the y-axis + + \note Please note the order of zLimit and yLimit. + + @see setSwingLimit() + */ + virtual void getSwingLimit(PxReal& zLimit, PxReal& yLimit) const = 0; + + /** + \brief set the tangential spring for the limit cone + Range: ([0, PX_MAX_F32), [0, PX_MAX_F32)) + Default: (0.0, 0.0) + */ + virtual void setTangentialStiffness(PxReal spring) = 0; + + /** + \brief get the tangential spring for the swing limit cone + + \return the tangential spring + + @see setTangentialStiffness() + */ + virtual PxReal getTangentialStiffness() const = 0; + + /** + \brief set the tangential damping for the limit cone + Range: ([0, PX_MAX_F32), [0, PX_MAX_F32)) + Default: (0.0, 0.0) + */ + virtual void setTangentialDamping(PxReal damping) = 0; + + /** + \brief get the tangential damping for the swing limit cone + + \return the tangential damping + + @see setTangentialDamping() + */ + virtual PxReal getTangentialDamping() const = 0; + + /** + \brief set the contact distance for the swing limit + + The contact distance should be less than either limit angle. + + Range: [0, Pi] + Default: 0.05 radians + + @see getSwingLimitContactDistance() + */ + virtual void setSwingLimitContactDistance(PxReal contactDistance) = 0; + + /** + \brief get the contact distance for the swing limit + + \return the contact distance for the swing limit cone + + @see setSwingLimitContactDistance() + */ + virtual PxReal getSwingLimitContactDistance() const = 0; + + /** + \brief set the flag which enables the swing limit + + \param[in] enabled whether the limit is enabled + Default: false + + @see getSwingLimitEnabled() + */ + virtual void setSwingLimitEnabled(bool enabled) = 0; + + /** + \brief get the flag which enables the swing limit + + \return whether the swing limit is enabled + + @see setSwingLimitEnabled() + */ + virtual bool getSwingLimitEnabled() const = 0; + + /** + \brief set the bounds of the twistLimit + + \param[in] lower the lower extent of the twist limit + \param[in] upper the upper extent of the twist limit + Range: (-Pi, Pi) + Default: (-Pi/4, Pi/4) + + The lower limit value must be less than the upper limit if the limit is enabled + + @see getTwistLimit() + */ + virtual void setTwistLimit(PxReal lower, PxReal upper) = 0; + + /** + \brief get the bounds of the twistLimit + + \param[out] lower the lower extent of the twist limit + \param[out] upper the upper extent of the twist limit + + @see setTwistLimit() + */ + virtual void getTwistLimit(PxReal &lower, PxReal &upper) const = 0; + + /** + \brief set the flag which enables the twist limit + + \param[in] enabled whether the twist limit is enabled + Default: false + + @see getTwistLimitEnabled() + */ + virtual void setTwistLimitEnabled(bool enabled) = 0; + + /** + \brief get the twistLimitEnabled flag + + \return whether the twist limit is enabled + + @see setTwistLimitEnabled() + */ + virtual bool getTwistLimitEnabled() const = 0; + + /** + \brief set the contact distance for the swing limit + + The contact distance should be less than half the distance between the upper and lower limits. + + Range: [0, Pi) + Default: 0.05 radians + + @see getTwistLimitContactDistance() + */ + virtual void setTwistLimitContactDistance(PxReal contactDistance) = 0; + + /** + \brief get the contact distance for the swing limit + + \return the contact distance for the twist limit + + @see setTwistLimitContactDistance() + */ + virtual PxReal getTwistLimitContactDistance() const = 0; + + virtual const char* getConcreteTypeName() const { return "PxArticulationJoint"; } + +protected: + PX_INLINE PxArticulationJoint(PxType concreteType, PxBaseFlags baseFlags) : PxArticulationJointBase(concreteType, baseFlags) {} + PX_INLINE PxArticulationJoint(PxBaseFlags baseFlags) : PxArticulationJointBase(baseFlags) {} + virtual ~PxArticulationJoint() {} + virtual bool isKindOf(const char* name) const { return !::strcmp("PxArticulationJoint", name) || PxArticulationJointBase::isKindOf(name); } +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/PxArticulationJointReducedCoordinate.h b/sources/PhysX/PhysX/include/PxArticulationJointReducedCoordinate.h new file mode 100644 index 00000000..bba5e3b9 --- /dev/null +++ b/sources/PhysX/PhysX/include/PxArticulationJointReducedCoordinate.h @@ -0,0 +1,95 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX_ARTICULATION_JOINT_RC +#define PX_PHYSICS_NX_ARTICULATION_JOINT_RC +/** \addtogroup physics +@{ */ + +#if 1 +#include "PxPhysXConfig.h" +#include "common/PxBase.h" +#include "PxArticulationJoint.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + + /** + \brief a joint between two links in an articulation. + + The joint model is very similar to a PxSphericalJoint with swing and twist limits, + and an implicit drive model. + + @see PxArticulation PxArticulationLink + */ + + class PxArticulationJointReducedCoordinate : public PxArticulationJointBase + { + public: + + virtual void setJointType(PxArticulationJointType::Enum jointType) = 0; + virtual PxArticulationJointType::Enum getJointType() const = 0; + + virtual void setMotion(PxArticulationAxis::Enum axis, PxArticulationMotion::Enum motion) = 0; + virtual PxArticulationMotion::Enum getMotion(PxArticulationAxis::Enum axis) const = 0; + + virtual void setLimit(PxArticulationAxis::Enum axis, const PxReal lowLimit, const PxReal highLimit) = 0; + virtual void getLimit(PxArticulationAxis::Enum axis, PxReal& lowLimit, PxReal& highLimit) = 0; + virtual void setDrive(PxArticulationAxis::Enum axis, const PxReal stiffness, const PxReal damping, const PxReal maxForce, PxArticulationDriveType::Enum driveType = PxArticulationDriveType::eFORCE) = 0; + virtual void getDrive(PxArticulationAxis::Enum axis, PxReal& stiffness, PxReal& damping, PxReal& maxForce, PxArticulationDriveType::Enum& driveType) = 0; + virtual void setDriveTarget(PxArticulationAxis::Enum axis, const PxReal target) = 0; + virtual void setDriveVelocity(PxArticulationAxis::Enum axis, const PxReal targetVel) = 0; + virtual PxReal getDriveTarget(PxArticulationAxis::Enum axis) = 0; + virtual PxReal getDriveVelocity(PxArticulationAxis::Enum axis) = 0; + + virtual void setFrictionCoefficient(const PxReal coefficient) = 0; + virtual PxReal getFrictionCoefficient() const = 0; + virtual const char* getConcreteTypeName() const { return "PxArticulationJointReducedCoordinate"; } + + virtual void setMaxJointVelocity(const PxReal maxJointV) = 0; + virtual PxReal getMaxJointVelocity() const = 0; + + protected: + PX_INLINE PxArticulationJointReducedCoordinate(PxType concreteType, PxBaseFlags baseFlags) : PxArticulationJointBase(concreteType, baseFlags) {} + PX_INLINE PxArticulationJointReducedCoordinate(PxBaseFlags baseFlags) : PxArticulationJointBase(baseFlags) {} + virtual ~PxArticulationJointReducedCoordinate() {} + virtual bool isKindOf(const char* name) const { return !::strcmp("PxArticulationJointReducedCoordinate", name) || PxBase::isKindOf(name); } + }; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +#endif + + /** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/PxArticulationLink.h b/sources/PhysX/PhysX/include/PxArticulationLink.h new file mode 100644 index 00000000..4b9fee71 --- /dev/null +++ b/sources/PhysX/PhysX/include/PxArticulationLink.h @@ -0,0 +1,139 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX_ARTICULATION_LINK +#define PX_PHYSICS_NX_ARTICULATION_LINK +/** \addtogroup physics +@{ */ + +#include "PxPhysXConfig.h" +#include "PxArticulationJoint.h" +#include "PxRigidBody.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + + class PxArticulationBase; + +/** +\brief a component of an articulation that represents a rigid body + +A limited subset of the properties of PxRigidDynamic are supported. In particular, sleep properties +are attributes of the articulation rather than each individual body, damping and velocity limits +are not supported, and links may not be kinematic. + +@see PxArticulation PxArticulation.createLink PxArticulationJoint PxRigidBody +*/ + +class PxArticulationLink : public PxRigidBody +{ +public: + /** + \brief Deletes the articulation link. + + \note Only a leaf articulation link can be released + + Do not keep a reference to the deleted instance. + + @see PxArticulation::createLink() + */ + virtual void release() = 0; + + /** + \brief get the articulation to which this articulation link belongs. This returns the base class. The application should + establish which articulation implementation this actually is and upcast to that type to access non-common functionality + + \return the articulation to which this link belongs + */ + virtual PxArticulationBase& getArticulation() const = 0; + + /** + \brief Get the joint which connects this link to its parent. + + \return The joint connecting the link to the parent. NULL for the root link. + + @see PxArticulationJoint + */ + virtual PxArticulationJointBase* getInboundJoint() const = 0; + + /** + \brief Get the degree of freedom of the joint which connects this link to its parent. + + \return The degree of freeedom of the joint connecting the link to the parent. 0xffffffff for the root link. + + @see PxArticulationJoint + */ + virtual PxU32 getInboundJointDof() const = 0; + + /** + \brief Get number of child links. + + \return the number of child links + + @see getChildren() + */ + virtual PxU32 getNbChildren() const = 0; + + /** + \brief Get low-level link index + + \return low-level index + */ + virtual PxU32 getLinkIndex() const = 0; + + /** + \brief Retrieve all the child links. + + \param[out] userBuffer The buffer to receive articulation link pointers. + \param[in] bufferSize Size of provided user buffer. + \return Number of articulation links written to the buffer. + \param[in] startIndex Index of first child pointer to be retrieved + + @see getNbChildren() + */ + virtual PxU32 getChildren(PxArticulationLink** userBuffer, PxU32 bufferSize, PxU32 startIndex=0) const = 0; + + virtual const char* getConcreteTypeName() const { return "PxArticulationLink"; } + +protected: + PX_INLINE PxArticulationLink(PxType concreteType, PxBaseFlags baseFlags) : PxRigidBody(concreteType, baseFlags) {} + PX_INLINE PxArticulationLink(PxBaseFlags baseFlags) : PxRigidBody(baseFlags) {} + virtual ~PxArticulationLink() {} + virtual bool isKindOf(const char* name) const { return !::strcmp("PxArticulationLink", name) || PxRigidBody::isKindOf(name); } +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/PxArticulationReducedCoordinate.h b/sources/PhysX/PhysX/include/PxArticulationReducedCoordinate.h new file mode 100644 index 00000000..a3acd8e5 --- /dev/null +++ b/sources/PhysX/PhysX/include/PxArticulationReducedCoordinate.h @@ -0,0 +1,422 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX_ARTICULATION_RC +#define PX_PHYSICS_NX_ARTICULATION_RC +/** \addtogroup physics +@{ */ + +#include "PxArticulationBase.h" +#include "foundation/PxVec3.h" +#include "foundation/PxTransform.h" +#include "solver/PxSolverDefs.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + + PX_ALIGN_PREFIX(16) + struct PxSpatialForce + { + PxVec3 force; + PxReal pad0; + PxVec3 torque; + PxReal pad1; + } + PX_ALIGN_SUFFIX(16); + + PX_ALIGN_PREFIX(16) + struct PxSpatialVelocity + { + PxVec3 linear; + PxReal pad0; + PxVec3 angular; + PxReal pad1; + } + PX_ALIGN_SUFFIX(16); + + class PxJoint; + + struct PxArticulationRootLinkData + { + PxTransform transform; + PxVec3 worldLinVel; + PxVec3 worldAngVel; + PxVec3 worldLinAccel; + PxVec3 worldAngAccel; + }; + + class PxArticulationCache + { + public: + enum Enum + { + eVELOCITY = (1 << 0), //!< The joint velocities this frame. Note, this is the accumulated joint velocities, not change in joint velocity. + eACCELERATION = (1 << 1), //!< The joint accelerations this frame. Delta velocity can be computed from acceleration * dt. + ePOSITION = (1 << 2), //!< The joint positions this frame. Note, this is the accumulated joint positions over frames, not change in joint position. + eFORCE = (1 << 3), //!< The joint forces this frame. Note, the application should provide these values for the forward dynamic. If the application is using inverse dynamic, this is the joint force returned. + eLINKVELOCITY = (1 << 4), //!< The link velocities this frame. + eLINKACCELERATION = (1 << 5), //!< The link accelerations this frame. + eROOT = (1 << 6), //!< Root link transform, velocity and acceleration. Note, when the application call applyCache with eROOT flag, it won't apply root link's acceleration to the simulation + eALL = (eVELOCITY | eACCELERATION | ePOSITION| eLINKVELOCITY | eLINKACCELERATION | eROOT ) + }; + PxArticulationCache() : + externalForces (NULL), + denseJacobian (NULL), + massMatrix (NULL), + jointVelocity (NULL), + jointAcceleration (NULL), + jointPosition (NULL), + jointForce (NULL), + rootLinkData (NULL), + coefficientMatrix (NULL), + lambda (NULL), + scratchMemory (NULL), + scratchAllocator (NULL), + version (0) + {} + + PxSpatialForce* externalForces; // N = getNbLinks() + PxReal* denseJacobian; // N = 6*getDofs()*NumJoints, NumJoints = getNbLinks() - 1 + PxReal* massMatrix; // N = getDofs()*getDofs() + PxReal* jointVelocity; // N = getDofs() + PxReal* jointAcceleration; // N = getDofs() + PxReal* jointPosition; // N = getDofs() + PxReal* jointForce; // N = getDofs() + PxSpatialVelocity* linkVelocity; // N = getNbLinks() + PxSpatialVelocity* linkAcceleration; // N = getNbLinks() + PxArticulationRootLinkData* rootLinkData; // root link Data + + //application need to allocate those memory and assign them to the cache + PxReal* coefficientMatrix; + PxReal* lambda; + + //These three members won't be set to zero when zeroCache get called + void* scratchMemory; //this is used for internal calculation + void* scratchAllocator; + PxU32 version; //cache version. If the articulation configuration change, the cache is invalid + }; + + typedef PxFlags PxArticulationCacheFlags; + PX_FLAGS_OPERATORS(PxArticulationCache::Enum, PxU8) + + /** + \brief a tree structure of bodies connected by joints that is treated as a unit by the dynamics solver + + Articulations are more expensive to simulate than the equivalent collection of + PxRigidDynamic and PxJoint structures, but because the dynamics solver treats + each articulation as a single object, they are much less prone to separation and + have better support for actuation. An articulation may have at most 64 links. + + @see PxArticulationJoint PxArticulationLink PxPhysics.createArticulation + */ + +#if PX_VC +#pragma warning(push) +#pragma warning(disable : 4435) +#endif + + class PxArticulationReducedCoordinate : public PxArticulationBase + { + public: + + virtual void release() = 0; + + /** + \brief Sets flags on the articulation + + \param[in] flags Articulation flags + + */ + virtual void setArticulationFlags(PxArticulationFlags flags) = 0; + + /** + \brief Raises or clears a flag on the articulation + + \param[in] flag The articulation flag + \param[in] value true/false indicating whether to raise or clear the flag + + */ + virtual void setArticulationFlag(PxArticulationFlag::Enum flag, bool value) = 0; + + /** + \brief return PxArticulationFlags + */ + virtual PxArticulationFlags getArticulationFlags() const = 0; + + /** + \brief returns the total Dofs of the articulation + */ + virtual PxU32 getDofs() const = 0; + + /** + \brief create an articulation cache + + \note this call may only be made on articulations that are in a scene, and may not be made during simulation + */ + virtual PxArticulationCache* createCache() const = 0; + + /** + \brief Get the size of the articulation cache + + \note this call may only be made on articulations that are in a scene, and may not be made during simulation + */ + virtual PxU32 getCacheDataSize() const = 0; + + /** + \brief zero all data in the articulation cache beside the cache version + + \note this call may only be made on articulations that are in a scene, and may not be made during simulation + */ + virtual void zeroCache(PxArticulationCache& cache) = 0; + + /** + \brief apply the user defined data in the cache to the articulation system + + \param[in] cache articulation data. + \param[in] flag The mode to use when determine which value in the cache will be applied to the articulation + \param[in] autowake Specify if the call should wake up the articulation if it is currently asleep. If true and the current wake counter value is smaller than #PxSceneDesc::wakeCounterResetValue it will get increased to the reset value. + + @see createCache copyInternalStateToCache + */ + virtual void applyCache(PxArticulationCache& cache, const PxArticulationCacheFlags flag, bool autowake = true) = 0; + + /** + \brief copy the internal data of the articulation to the cache + + \param[in] cache articulation data + \param[in] flag this indicates what kind of data the articulation system need to copy to the cache + + @see createCache applyCache + */ + virtual void copyInternalStateToCache(PxArticulationCache& cache, const PxArticulationCacheFlags flag) const = 0; + + /** + \brief release an articulation cache + + \param[in] cache the cache to release + + @see createCache applyCache copyInternalStateToCache + */ + virtual void releaseCache(PxArticulationCache& cache) const = 0; + + /** + \brief reduce the maximum data format to the reduced internal data + \param[in] maximum joint data format + \param[out] reduced joint data format + */ + virtual void packJointData(const PxReal* maximum, PxReal* reduced) const = 0; + + /** + \brief turn the reduced internal data to maximum joint data format + \param[in] reduced joint data format + \param[out] maximum joint data format + */ + virtual void unpackJointData(const PxReal* reduced, PxReal* maximum) const = 0; + + /** + \brief initialize all the common data for inverse dynamics + */ + virtual void commonInit() const = 0; + + /** + \brief determine the statically balance of the joint force of gravity for entire articulation. External force, joint velocity and joint acceleration + are set to zero, the joint force returned will be purely determined by gravity. + + \param[out] cache return joint forces which can counteract gravity force + + @see commonInit + */ + virtual void computeGeneralizedGravityForce(PxArticulationCache& cache) const = 0; + + /** + \brief determine coriolise and centrifugal force. External force, gravity and joint acceleration + are set to zero, the joint force return will be coriolise and centrifugal force for each joint. + + \param[in] cache data + + @see commonInit + */ + virtual void computeCoriolisAndCentrifugalForce(PxArticulationCache& cache) const = 0; + + /** + \brief determine joint force change caused by external force. Gravity, joint acceleration and joint velocity + are all set to zero. + + \param[in] cache data + + @see commonInit + */ + virtual void computeGeneralizedExternalForce(PxArticulationCache& cache) const = 0; + + /** + \brief determine the joint acceleration for each joint + This is purely calculates the change in joint acceleration due to change in the joint force + + \param[in] cache articulation data + + @see commonInit + */ + virtual void computeJointAcceleration(PxArticulationCache& cache) const = 0; + + /** + \brief determine the joint force + This is purely calculates the change in joint force due to change in the joint acceleration + This means gravity and joint velocity will be zero + + \param[in] cache return joint force + + @see commonInit + */ + virtual void computeJointForce(PxArticulationCache& cache) const = 0; + + /** + \brief compute the dense Jacobian for the entire articulation in world space + \param[out] cache sets cache.denseJacobian matrix. The matrix is indexed [nCols * row + column]. + \param[out] nRows set to number of rows in matrix, which corresponds to the number of articulation links times 6. + \param[out] nCols set to number of columns in matrix, which corresponds to the number of joint DOFs, plus 6 in the case eFIX_BASE is false. + + Note that this computes the dense representation of an inherently sparse matrix. Multiplication with this matrix maps + joint space velocities to 6DOF world space linear and angular velocities. + */ + virtual void computeDenseJacobian(PxArticulationCache& cache, PxU32& nRows, PxU32& nCols) const = 0; + + + /** + \brief compute the coefficient matrix for contact force. + \param[out] cache returns the coefficient matrix. Each column is the joint force effected by a contact based on impulse strength 1 + @see commonInit + */ + virtual void computeCoefficientMatrix(PxArticulationCache& cache) const = 0; + + /** + \brief compute the lambda value when the test impulse is 1 + \param[in] initialState the initial state of the articulation system + \param[in] jointTorque M(q)*qddot + C(q,qdot) + g(q) + \param[in] maxIter maximum number of solver iterations to run. If the system converges, fewer iterations may be used. + \param[out] cache returns the coefficient matrix. Each column is the joint force effected by a contact based on impulse strength 1 + @see commonInit + */ + virtual bool computeLambda(PxArticulationCache& cache, PxArticulationCache& initialState, const PxReal* const jointTorque, const PxU32 maxIter) const = 0; + + /** + \brief compute the joint-space inertia matrix + \param[in] cache articulation data + + @see commonInit + */ + virtual void computeGeneralizedMassMatrix(PxArticulationCache& cache) const = 0; + + /** + \brief add loop joint to the articulation system for inverse dynamic + \param[in] joint required to add loop joint + + @see commonInit + */ + virtual void addLoopJoint(PxJoint* joint) = 0; + + /** + \brief remove loop joint from the articulation system + \param[in] joint required to remove loop joint + + @see commonInit + */ + virtual void removeLoopJoint(PxJoint* joint) = 0; + + /** + \brief returns the number of loop joints in the articulation + \return number of loop joints + */ + virtual PxU32 getNbLoopJoints() const = 0; + + /** + \brief returns the set of loop constraints in the articulation + + \param[in] userBuffer buffer into which to write an array of constraints pointers + \param[in] bufferSize the size of the buffer. If this is not large enough to contain all the pointers to links, + only as many as will fit are written. + \param[in] startIndex Index of first link pointer to be retrieved + + \return the number of links written into the buffer. + + @see ArticulationLink + */ + virtual PxU32 getLoopJoints(PxJoint** userBuffer, PxU32 bufferSize, PxU32 startIndex = 0) const = 0; + + /** + \brief returns the required size of coeffient matrix in the articulation. The coefficient matrix is number of constraint(loop joints) by total dofs. Constraint Torque = transpose(K) * lambda(). Lambda is a vector of number of constraints + \return bite size of the coefficient matrix(nc * n) + */ + virtual PxU32 getCoefficientMatrixSize() const = 0; + + /** + \brief teleport root link to a new location + \param[in] pose the new location of the root link + \param[in] autowake wake up the articulation system + + @see commonInit + */ + virtual void teleportRootLink(const PxTransform& pose, bool autowake) = 0; + + + /** + \brief return the link velocity in world space with the associated low-level link index(getLinkIndex()). + \param[in] linkId low-level link index + + @see getLinkIndex() in PxArticulationLink + */ + virtual PxSpatialVelocity getLinkVelocity(const PxU32 linkId) = 0; + + + /** + \brief return the link acceleration in world space with the associated low-level link index(getLinkIndex()) + \param[in] linkId low-level link index + + @see getLinkIndex() in PxArticulationLink + */ + virtual PxSpatialVelocity getLinkAcceleration(const PxU32 linkId) = 0; + + protected: + PX_INLINE PxArticulationReducedCoordinate(PxType concreteType, PxBaseFlags baseFlags) : PxArticulationBase(concreteType, baseFlags) {} + PX_INLINE PxArticulationReducedCoordinate(PxBaseFlags baseFlags) : PxArticulationBase(baseFlags) {} + virtual ~PxArticulationReducedCoordinate() {} + }; + +#if PX_VC +#pragma warning(pop) +#endif + +#if !PX_DOXYGEN +} // namespace physx +#endif + + /** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/PxBatchQuery.h b/sources/PhysX/PhysX/include/PxBatchQuery.h new file mode 100644 index 00000000..6dc4eaa2 --- /dev/null +++ b/sources/PhysX/PhysX/include/PxBatchQuery.h @@ -0,0 +1,224 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX_SCENEQUERY +#define PX_PHYSICS_NX_SCENEQUERY +/** \addtogroup scenequery +@{ */ + +#include "PxPhysXConfig.h" +#include "PxShape.h" +#include "PxBatchQueryDesc.h" +#include "PxQueryFiltering.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxBoxGeometry; +class PxSphereGeometry; +struct PxQueryCache; + +/** +\brief Batched queries object. This is used to perform several queries at the same time. + +\deprecated The batched query feature has been deprecated in PhysX version 3.4 + +@see PxScene, PxScene.createBatchQuery +*/ +class PX_DEPRECATED PxBatchQuery +{ + public: + + /** + \brief Executes batched queries. + */ + virtual void execute() = 0; + + /** + \brief Gets the prefilter shader in use for this scene query. + + \return Prefilter shader. + + @see PxBatchQueryDesc.preFilterShade PxBatchQueryPreFilterShader + */ + virtual PxBatchQueryPreFilterShader getPreFilterShader() const = 0; + + /** + \brief Gets the postfilter shader in use for this scene query. + + \return Postfilter shader. + + @see PxBatchQueryDesc.preFilterShade PxBatchQueryPostFilterShader + */ + virtual PxBatchQueryPostFilterShader getPostFilterShader() const = 0; + + + /** + \brief Gets the shared global filter data in use for this scene query. + + \return Shared filter data for filter shader. + + @see getFilterShaderDataSize() PxBatchQueryDesc.filterShaderData PxBatchQueryPreFilterShader, PxBatchQueryPostFilterShader + */ + virtual const void* getFilterShaderData() const = 0; + + /** + \brief Gets the size of the shared global filter data (#PxSceneDesc.filterShaderData) + + \return Size of shared filter data [bytes]. + + @see getFilterShaderData() PxBatchQueryDesc.filterShaderDataSize PxBatchQueryPreFilterShader, PxBatchQueryPostFilterShader + */ + virtual PxU32 getFilterShaderDataSize() const = 0; + + /** + \brief Sets new user memory pointers. + + It is not possible to change the memory during query execute. + + @see PxBatchQueryDesc + */ + virtual void setUserMemory(const PxBatchQueryMemory&) = 0; + + /** + \brief Gets the user memory pointers. + + @see PxBatchQueryDesc + */ + virtual const PxBatchQueryMemory& getUserMemory() = 0; + + /** + \brief Releases PxBatchQuery from PxScene + + @see PxScene, PxScene.createBatchQuery + */ + virtual void release() = 0; + + /** + \brief Performs a raycast against objects in the scene, returns results in PxBatchQueryMemory::userRaycastResultBuffer + specified at PxBatchQuery creation time or via PxBatchQuery::setUserMemory call. + + \note Touching hits are not ordered. + \note Shooting a ray from within an object leads to different results depending on the shape type. Please check the details in article SceneQuery. User can ignore such objects by using one of the provided filter mechanisms. + + \param[in] origin Origin of the ray. + \param[in] unitDir Normalized direction of the ray. + \param[in] distance Length of the ray. Needs to be larger than 0. + \param[in] maxTouchHits Maximum number of hits to record in the touch buffer for this query. Default=0 reports a single blocking hit. If maxTouchHits is set to 0 all hits are treated as blocking by default. + \param[in] hitFlags Specifies which properties per hit should be computed and returned in hit array and blocking hit. + \param[in] filterData Filtering data passed to the filter shader. See #PxQueryFilterData #PxBatchQueryPreFilterShader, #PxBatchQueryPostFilterShader + \param[in] userData User can pass any value in this argument, usually to identify this particular query + \param[in] cache Cached hit shape (optional). Query is tested against cached shape first. If no hit is found the ray gets queried against the scene. + Note: Filtering is not executed for a cached shape if supplied; instead, if a hit is found, it is assumed to be a blocking hit. + Note: Using past touching hits as cache will produce incorrect behavior since the cached hit will always be treated as blocking. + + \note This query call writes to a list associated with the query object and is NOT thread safe (for performance reasons there is no lock + and overlapping writes from different threads may result in undefined behavior). + + @see PxQueryFilterData PxBatchQueryPreFilterShader PxBatchQueryPostFilterShader PxRaycastHit PxScene::raycast + */ + virtual void raycast( + const PxVec3& origin, const PxVec3& unitDir, PxReal distance = PX_MAX_F32, PxU16 maxTouchHits = 0, + PxHitFlags hitFlags = PxHitFlag::eDEFAULT, + const PxQueryFilterData& filterData = PxQueryFilterData(), + void* userData = NULL, const PxQueryCache* cache = NULL) = 0; + + + /** + \brief Performs an overlap test of a given geometry against objects in the scene, returns results in PxBatchQueryMemory::userOverlapResultBuffer + specified at PxBatchQuery creation time or via PxBatchQuery::setUserMemory call. + + \note Filtering: returning eBLOCK from user filter for overlap queries will cause a warning (see #PxQueryHitType). + + \param[in] geometry Geometry of object to check for overlap (supported types are: box, sphere, capsule, convex). + \param[in] pose Pose of the object. + \param[in] maxTouchHits Maximum number of hits to record in the touch buffer for this query. Default=0 reports a single blocking hit. If maxTouchHits is set to 0 all hits are treated as blocking by default. + \param[in] filterData Filtering data and simple logic. See #PxQueryFilterData #PxBatchQueryPreFilterShader, #PxBatchQueryPostFilterShader + \param[in] userData User can pass any value in this argument, usually to identify this particular query + \param[in] cache Cached hit shape (optional). Query is tested against cached shape first. If no hit is found the ray gets queried against the scene. + Note: Filtering is not executed for a cached shape if supplied; instead, if a hit is found, it is assumed to be a blocking hit. + Note: Using past touching hits as cache will produce incorrect behavior since the cached hit will always be treated as blocking. + + \note eBLOCK should not be returned from user filters for overlap(). Doing so will result in undefined behavior, and a warning will be issued. + \note If the PxQueryFlag::eNO_BLOCK flag is set, the eBLOCK will instead be automatically converted to an eTOUCH and the warning suppressed. + \note This query call writes to a list associated with the query object and is NOT thread safe (for performance reasons there is no lock + and overlapping writes from different threads may result in undefined behavior). + + @see PxQueryFilterData PxBatchQueryPreFilterShader PxBatchQueryPostFilterShader + */ + virtual void overlap( + const PxGeometry& geometry, const PxTransform& pose, PxU16 maxTouchHits = 0, + const PxQueryFilterData& filterData = PxQueryFilterData(), void* userData=NULL, const PxQueryCache* cache = NULL) = 0; + + /** + \brief Performs a sweep test against objects in the scene, returns results in PxBatchQueryMemory::userSweepResultBuffer + specified at PxBatchQuery creation time or via PxBatchQuery::setUserMemory call. + + \note Touching hits are not ordered. + \note If a shape from the scene is already overlapping with the query shape in its starting position, + the hit is returned unless eASSUME_NO_INITIAL_OVERLAP was specified. + + \param[in] geometry Geometry of object to sweep (supported types are: box, sphere, capsule, convex). + \param[in] pose Pose of the sweep object. + \param[in] unitDir Normalized direction of the sweep. + \param[in] distance Sweep distance. Needs to be larger than 0. Will be clamped to PX_MAX_SWEEP_DISTANCE. + \param[in] maxTouchHits Maximum number of hits to record in the touch buffer for this query. Default=0 reports a single blocking hit. If maxTouchHits is set to 0 all hits are treated as blocking by default. + \param[in] hitFlags Specifies which properties per hit should be computed and returned in hit array and blocking hit. + \param[in] filterData Filtering data and simple logic. See #PxQueryFilterData #PxBatchQueryPreFilterShader, #PxBatchQueryPostFilterShader + \param[in] userData User can pass any value in this argument, usually to identify this particular query + \param[in] cache Cached hit shape (optional). Query is tested against cached shape first. If no hit is found the ray gets queried against the scene. + Note: Filtering is not executed for a cached shape if supplied; instead, if a hit is found, it is assumed to be a blocking hit. + Note: Using past touching hits as cache will produce incorrect behavior since the cached hit will always be treated as blocking. + \param[in] inflation This parameter creates a skin around the swept geometry which increases its extents for sweeping. The sweep will register a hit as soon as the skin touches a shape, and will return the corresponding distance and normal. + Note: ePRECISE_SWEEP doesn't support inflation. Therefore the sweep will be performed with zero inflation. + + \note This query call writes to a list associated with the query object and is NOT thread safe (for performance reasons there is no lock + and overlapping writes from different threads may result in undefined behavior). + + @see PxHitFlags PxQueryFilterData PxBatchQueryPreFilterShader PxBatchQueryPostFilterShader PxSweepHit + */ + virtual void sweep( + const PxGeometry& geometry, const PxTransform& pose, const PxVec3& unitDir, const PxReal distance, + PxU16 maxTouchHits = 0, PxHitFlags hitFlags = PxHitFlag::eDEFAULT, + const PxQueryFilterData& filterData = PxQueryFilterData(), void* userData=NULL, const PxQueryCache* cache = NULL, + const PxReal inflation = 0.f) = 0; + +protected: + virtual ~PxBatchQuery() {} +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/PxBatchQueryDesc.h b/sources/PhysX/PhysX/include/PxBatchQueryDesc.h new file mode 100644 index 00000000..338db6fb --- /dev/null +++ b/sources/PhysX/PhysX/include/PxBatchQueryDesc.h @@ -0,0 +1,303 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX_SCENEQUERYDESC +#define PX_PHYSICS_NX_SCENEQUERYDESC +/** \addtogroup physics +@{ */ + +#include "PxPhysXConfig.h" +#include "PxClient.h" +#include "PxFiltering.h" +#include "PxQueryFiltering.h" +#include "foundation/PxAssert.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +struct PxSweepHit; +struct PxRaycastHit; + +/** +\brief Batched query status. + +\deprecated The batched query feature has been deprecated in PhysX version 3.4 +*/ +struct PX_DEPRECATED PxBatchQueryStatus +{ + enum Enum + { + /** + \brief This is the initial state before a query starts. + */ + ePENDING = 0, + + /** + \brief The query is finished; results have been written into the result and hit buffers. + */ + eSUCCESS, + + /** + \brief The query results were incomplete due to touch hit buffer overflow. Blocking hit is still correct. + */ + eOVERFLOW + }; +}; + +/** +\brief Generic struct for receiving results of single query in a batch. Gets templated on hit type PxRaycastHit, PxSweepHit or PxOverlapHit. + +\deprecated The batched query feature has been deprecated in PhysX version 3.4 +*/ +template +struct PX_DEPRECATED PxBatchQueryResult +{ + HitType block; //!< Holds the closest blocking hit for a single query in a batch. Only valid if hasBlock is true. + HitType* touches; //!< This pointer will either be set to NULL for 0 nbTouches or will point + //!< into the user provided batch query results buffer specified in PxBatchQueryDesc. + PxU32 nbTouches; //!< Number of touching hits returned by this query, works in tandem with touches pointer. + void* userData; //!< Copy of the userData pointer specified in the corresponding query. + PxU8 queryStatus; //!< Takes on values from PxBatchQueryStatus::Enum. + bool hasBlock; //!< True if there was a blocking hit. + PxU16 pad; //!< pads the struct to 16 bytes. + + /** \brief Computes the number of any hits in this result, blocking or touching. */ + PX_INLINE PxU32 getNbAnyHits() const { return nbTouches + (hasBlock ? 1 : 0); } + + /** \brief Convenience iterator used to access any hits in this result, blocking or touching. */ + PX_INLINE const HitType& getAnyHit(const PxU32 index) const { PX_ASSERT(index < nbTouches + (hasBlock ? 1 : 0)); + return index < nbTouches ? touches[index] : block; } +}; + +/** \brief Convenience typedef for the result of a batched raycast query. */ +typedef PX_DEPRECATED PxBatchQueryResult PxRaycastQueryResult; + +/** \brief Convenience typedef for the result of a batched sweep query. */ +typedef PX_DEPRECATED PxBatchQueryResult PxSweepQueryResult; + +/** \brief Convenience typedef for the result of a batched overlap query. */ +typedef PX_DEPRECATED PxBatchQueryResult PxOverlapQueryResult; + +/** +\brief Struct for #PxBatchQuery memory pointers. + +\deprecated The batched query feature has been deprecated in PhysX version 3.4 + +@see PxBatchQuery PxBatchQueryDesc +*/ +struct PX_DEPRECATED PxBatchQueryMemory + { + /** + \brief The pointer to the user-allocated buffer for results of raycast queries in corresponding order of issue + + \note The size should be large enough to fit the number of expected raycast queries. + + @see PxRaycastQueryResult + */ + PxRaycastQueryResult* userRaycastResultBuffer; + + /** + \brief The pointer to the user-allocated buffer for raycast touch hits. + \note The size of this buffer should be large enough to store PxRaycastHit. + If the buffer is too small to store hits, the related PxRaycastQueryResult.queryStatus will be set to eOVERFLOW + + */ + PxRaycastHit* userRaycastTouchBuffer; + + /** + \brief The pointer to the user-allocated buffer for results of sweep queries in corresponding order of issue + + \note The size should be large enough to fit the number of expected sweep queries. + + @see PxRaycastQueryResult + */ + PxSweepQueryResult* userSweepResultBuffer; + + /** + \brief The pointer to the user-allocated buffer for sweep hits. + \note The size of this buffer should be large enough to store PxSweepHit. + If the buffer is too small to store hits, the related PxSweepQueryResult.queryStatus will be set to eOVERFLOW + + */ + PxSweepHit* userSweepTouchBuffer; + + /** + \brief The pointer to the user-allocated buffer for results of overlap queries in corresponding order of issue + + \note The size should be large enough to fit the number of expected overlap queries. + + @see PxRaycastQueryResult + */ + PxOverlapQueryResult* userOverlapResultBuffer; + + /** + \brief The pointer to the user-allocated buffer for overlap hits. + \note The size of this buffer should be large enough to store the hits returned. + If the buffer is too small to store hits, the related PxOverlapQueryResult.queryStatus will be set to eABORTED + + */ + PxOverlapHit* userOverlapTouchBuffer; + + /** \brief Capacity of the user-allocated userRaycastTouchBuffer in elements */ + PxU32 raycastTouchBufferSize; + + /** \brief Capacity of the user-allocated userSweepTouchBuffer in elements */ + PxU32 sweepTouchBufferSize; + + /** \brief Capacity of the user-allocated userOverlapTouchBuffer in elements */ + PxU32 overlapTouchBufferSize; + + /** \return Capacity of the user-allocated userRaycastResultBuffer in elements (max number of raycast() calls before execute() call) */ + PX_FORCE_INLINE PxU32 getMaxRaycastsPerExecute() const { return raycastResultBufferSize; } + + /** \return Capacity of the user-allocated userSweepResultBuffer in elements (max number of sweep() calls before execute() call) */ + PX_FORCE_INLINE PxU32 getMaxSweepsPerExecute() const { return sweepResultBufferSize; } + + /** \return Capacity of the user-allocated userOverlapResultBuffer in elements (max number of overlap() calls before execute() call) */ + PX_FORCE_INLINE PxU32 getMaxOverlapsPerExecute() const { return overlapResultBufferSize; } + + PxBatchQueryMemory(PxU32 raycastResultBufferSize_, PxU32 sweepResultBufferSize_, PxU32 overlapResultBufferSize_) : + userRaycastResultBuffer (NULL), + userRaycastTouchBuffer (NULL), + userSweepResultBuffer (NULL), + userSweepTouchBuffer (NULL), + userOverlapResultBuffer (NULL), + userOverlapTouchBuffer (NULL), + raycastTouchBufferSize (0), + sweepTouchBufferSize (0), + overlapTouchBufferSize (0), + raycastResultBufferSize (raycastResultBufferSize_), + sweepResultBufferSize (sweepResultBufferSize_), + overlapResultBufferSize (overlapResultBufferSize_) + { + } + +protected: + PxU32 raycastResultBufferSize; + PxU32 sweepResultBufferSize; + PxU32 overlapResultBufferSize; +}; + +/** +\brief Descriptor class for #PxBatchQuery. + +\deprecated The batched query feature has been deprecated in PhysX version 3.4 + +@see PxBatchQuery PxSceneQueryExecuteMode +*/ +class PX_DEPRECATED PxBatchQueryDesc +{ +public: + + /** + \brief Shared global filter data which will get passed into the filter shader. + + \note The provided data will get copied to internal buffers and this copy will be used for filtering calls. + + Default: NULL + + @see PxSimulationFilterShader + */ + void* filterShaderData; + + /** + \brief Size (in bytes) of the shared global filter data #filterShaderData. + + Default: 0 + + @see PxSimulationFilterShader filterShaderData + */ + PxU32 filterShaderDataSize; + + /** + \brief The custom preFilter shader to use for filtering. + + @see PxBatchQueryPreFilterShader PxDefaultPreFilterShader + */ + PxBatchQueryPreFilterShader preFilterShader; + + /** + \brief The custom postFilter shader to use for filtering. + + @see PxBatchQueryPostFilterShader PxDefaultPostFilterShader + */ + PxBatchQueryPostFilterShader postFilterShader; + + /** + \brief User memory buffers for the query. + + @see PxBatchQueryMemory + */ + PxBatchQueryMemory queryMemory; + + /** + \brief Construct a batch query with specified maximum number of queries per batch. + + If the number of raycasts/sweeps/overlaps per execute exceeds the limit, the query will be discarded with a warning. + + \param maxRaycastsPerExecute Maximum number of raycast() calls allowed before execute() call. + This has to match the amount of memory allocated for PxBatchQueryMemory::userRaycastResultBuffer. + \param maxSweepsPerExecute Maximum number of sweep() calls allowed before execute() call. + This has to match the amount of memory allocated for PxBatchQueryMemory::userSweepResultBuffer. + \param maxOverlapsPerExecute Maximum number of overlap() calls allowed before execute() call. + This has to match the amount of memory allocated for PxBatchQueryMemory::userOverlapResultBuffer. + */ + PX_INLINE PxBatchQueryDesc(PxU32 maxRaycastsPerExecute, PxU32 maxSweepsPerExecute, PxU32 maxOverlapsPerExecute); + PX_INLINE bool isValid() const; +}; + + +PX_INLINE PxBatchQueryDesc::PxBatchQueryDesc(PxU32 maxRaycastsPerExecute, PxU32 maxSweepsPerExecute, PxU32 maxOverlapsPerExecute) : + filterShaderData (NULL), + filterShaderDataSize (0), + preFilterShader (NULL), + postFilterShader (NULL), + queryMemory (maxRaycastsPerExecute, maxSweepsPerExecute, maxOverlapsPerExecute) +{ +} + + +PX_INLINE bool PxBatchQueryDesc::isValid() const +{ + if ( ((filterShaderDataSize == 0) && (filterShaderData != NULL)) || + ((filterShaderDataSize > 0) && (filterShaderData == NULL)) ) + return false; + + return true; +} + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/PxBroadPhase.h b/sources/PhysX/PhysX/include/PxBroadPhase.h new file mode 100644 index 00000000..91fd5deb --- /dev/null +++ b/sources/PhysX/PhysX/include/PxBroadPhase.h @@ -0,0 +1,174 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_BROAD_PHASE_H +#define PX_PHYSICS_BROAD_PHASE_H +/** \addtogroup physics +@{ +*/ + +#include "PxPhysXConfig.h" +#include "foundation/PxBounds3.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + + class PxActor; + + /** + \brief Broad phase algorithm used in the simulation + + eSAP is a good generic choice with great performance when many objects are sleeping. Performance + can degrade significantly though, when all objects are moving, or when large numbers of objects + are added to or removed from the broad phase. This algorithm does not need world bounds to be + defined in order to work. + + eMBP is an alternative broad phase algorithm that does not suffer from the same performance + issues as eSAP when all objects are moving or when inserting large numbers of objects. However + its generic performance when many objects are sleeping might be inferior to eSAP, and it requires + users to define world bounds in order to work. + + eABP is a revisited implementation of MBP, which automatically manages broad-phase regions. + It offers the convenience of eSAP (no need to define world bounds or regions) and the performance + of eMBP when a lot of objects are moving. While eSAP can remain faster when most objects are + sleeping and eMBP can remain faster when it uses a large number of properly-defined regions, + eABP often gives the best performance on average and the best memory usage. + */ + struct PxBroadPhaseType + { + enum Enum + { + eSAP, //!< 3-axes sweep-and-prune + eMBP, //!< Multi box pruning + eABP, //!< Automatic box pruning + eGPU, + + eLAST + }; + }; + + /** + \brief Broad-phase callback to receive broad-phase related events. + + Each broadphase callback object is associated with a PxClientID. It is possible to register different + callbacks for different clients. The callback functions are called this way: + - for shapes/actors, the callback assigned to the actors' clients are used + - for aggregates, the callbacks assigned to clients from aggregated actors are used + + \note SDK state should not be modified from within the callbacks. In particular objects should not + be created or destroyed. If state modification is needed then the changes should be stored to a buffer + and performed after the simulation step. + + Threading: It is not necessary to make this class thread safe as it will only be called in the context of the + user thread. + + @see PxSceneDesc PxScene.setBroadPhaseCallback() PxScene.getBroadPhaseCallback() + */ + class PxBroadPhaseCallback + { + public: + virtual ~PxBroadPhaseCallback() {} + + /** + \brief Out-of-bounds notification. + + This function is called when an object leaves the broad-phase. + + \param[in] shape Shape that left the broad-phase bounds + \param[in] actor Owner actor + */ + virtual void onObjectOutOfBounds(PxShape& shape, PxActor& actor) = 0; + + /** + \brief Out-of-bounds notification. + + This function is called when an aggregate leaves the broad-phase. + + \param[in] aggregate Aggregate that left the broad-phase bounds + */ + virtual void onObjectOutOfBounds(PxAggregate& aggregate) = 0; + }; + + /** + \brief "Region of interest" for the broad-phase. + + This is currently only used for the PxBroadPhaseType::eMBP broad-phase, which requires zones or regions to be defined + when the simulation starts in order to work. Regions can overlap and be added or removed at runtime, but at least one + region needs to be defined when the scene is created. + + If objects that do no overlap any region are inserted into the scene, they will not be added to the broad-phase and + thus collisions will be disabled for them. A PxBroadPhaseCallback out-of-bounds notification will be sent for each one + of those objects. + + The total number of regions is limited by PxBroadPhaseCaps::maxNbRegions. + + The number of regions has a direct impact on performance and memory usage, so it is recommended to experiment with + various settings to find the best combination for your game. A good default setup is to start with global bounds + around the whole world, and subdivide these bounds into 4*4 regions. The PxBroadPhaseExt::createRegionsFromWorldBounds + function can do that for you. + + @see PxBroadPhaseCallback PxBroadPhaseExt.createRegionsFromWorldBounds + */ + struct PxBroadPhaseRegion + { + PxBounds3 bounds; //!< Region's bounds + void* userData; //!< Region's user-provided data + }; + + /** + \brief Information & stats structure for a region + */ + struct PxBroadPhaseRegionInfo + { + PxBroadPhaseRegion region; //!< User-provided region data + PxU32 nbStaticObjects; //!< Number of static objects in the region + PxU32 nbDynamicObjects; //!< Number of dynamic objects in the region + bool active; //!< True if region is currently used, i.e. it has not been removed + bool overlap; //!< True if region overlaps other regions (regions that are just touching are not considering overlapping) + }; + + /** + \brief Caps class for broad phase. + */ + struct PxBroadPhaseCaps + { + PxU32 maxNbRegions; //!< Max number of regions supported by the broad-phase + PxU32 maxNbObjects; //!< Max number of objects supported by the broad-phase + bool needsPredefinedBounds; //!< If true, broad-phase needs 'regions' to work + }; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/PxClient.h b/sources/PhysX/PhysX/include/PxClient.h new file mode 100644 index 00000000..ce540e03 --- /dev/null +++ b/sources/PhysX/PhysX/include/PxClient.h @@ -0,0 +1,66 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX_CLIENT +#define PX_PHYSICS_NX_CLIENT + +#include "foundation/PxFlags.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief An ID to identify different clients for multiclient support. + +@see PxScene::createClient() +*/ +typedef PxU8 PxClientID; + +/** +\brief The predefined default PxClientID value. + +@see PxClientID PxScene::createClient() +*/ +static const PxClientID PX_DEFAULT_CLIENT = 0; + +/** +\brief The maximum number of clients we support. + +@see PxClientID PxScene::createClient() +*/ +static const PxClientID PX_MAX_CLIENTS = 128; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +#endif diff --git a/sources/PhysX/PhysX/include/PxConfig.h b/sources/PhysX/PhysX/include/PxConfig.h new file mode 100644 index 00000000..aec243fb --- /dev/null +++ b/sources/PhysX/PhysX/include/PxConfig.h @@ -0,0 +1,35 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. + + +#ifndef PX_CONFIG +#define PX_CONFIG + +#define PX_PHYSX_STATIC_LIB + + +#endif // PX_CONFIG diff --git a/sources/PhysX/PhysX/include/PxConstraint.h b/sources/PhysX/PhysX/include/PxConstraint.h new file mode 100644 index 00000000..0e64ff23 --- /dev/null +++ b/sources/PhysX/PhysX/include/PxConstraint.h @@ -0,0 +1,280 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_PHYSICS_NX_CONSTRAINT +#define PX_PHYSICS_NX_CONSTRAINT + +/** \addtogroup physics +@{ +*/ + +#include "PxPhysXConfig.h" +#include "PxConstraintDesc.h" +#include "common/PxBase.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxRigidActor; +class PxScene; +class PxConstraintConnector; + +/** +\brief a table of function pointers for a constraint + +@see PxConstraint +*/ + +/** +\brief constraint flags + +\note eBROKEN is a read only flag +*/ + +struct PxConstraintFlag +{ + enum Enum + { + eBROKEN = 1<<0, //!< whether the constraint is broken + ePROJECT_TO_ACTOR0 = 1<<1, //!< whether actor1 should get projected to actor0 for this constraint (note: projection of a static/kinematic actor to a dynamic actor will be ignored) + ePROJECT_TO_ACTOR1 = 1<<2, //!< whether actor0 should get projected to actor1 for this constraint (note: projection of a static/kinematic actor to a dynamic actor will be ignored) + ePROJECTION = ePROJECT_TO_ACTOR0 | ePROJECT_TO_ACTOR1, //!< whether the actors should get projected for this constraint (the direction will be chosen by PhysX) + eCOLLISION_ENABLED = 1<<3, //!< whether contacts should be generated between the objects this constraint constrains + eVISUALIZATION = 1<<4, //!< whether this constraint should be visualized, if constraint visualization is turned on + eDRIVE_LIMITS_ARE_FORCES = 1<<5, //!< limits for drive strength are forces rather than impulses + eIMPROVED_SLERP = 1<<7, //!< perform preprocessing for improved accuracy on D6 Slerp Drive (this flag will be removed in a future release when preprocessing is no longer required) + eDISABLE_PREPROCESSING = 1<<8, //!< suppress constraint preprocessing, intended for use with rowResponseThreshold. May result in worse solver accuracy for ill-conditioned constraints. + eENABLE_EXTENDED_LIMITS = 1<<9, //!< enables extended limit ranges for angular limits (e.g. limit values > PxPi or < -PxPi) + eGPU_COMPATIBLE = 1<<10 //!< the constraint type is supported by gpu dynamic + }; +}; + +/** +\brief constraint flags +@see PxConstraintFlag +*/ + +typedef PxFlags PxConstraintFlags; +PX_FLAGS_OPERATORS(PxConstraintFlag::Enum, PxU16) + +struct PxConstraintShaderTable +{ + enum + { + eMAX_SOLVERPRPEP_DATASIZE=400 + }; + + PxConstraintSolverPrep solverPrep; //!< solver constraint generation function + PxConstraintProject project; //!< constraint projection function + PxConstraintVisualize visualize; //!< constraint visualization function + PxConstraintFlag::Enum flag; //!< gpu constraint +}; + + +/** +\brief A plugin class for implementing constraints + +@see PxPhysics.createConstraint +*/ + +class PxConstraint : public PxBase +{ +public: + + /** + \brief Releases a PxConstraint instance. + + \note This call does not wake up the connected rigid bodies. + + @see PxPhysics.createConstraint, PxBase.release() + */ + virtual void release() = 0; + + /** + \brief Retrieves the scene which this constraint belongs to. + + \return Owner Scene. NULL if not part of a scene. + + @see PxScene + */ + virtual PxScene* getScene() const = 0; + + /** + \brief Retrieves the actors for this constraint. + + \param[out] actor0 a reference to the pointer for the first actor + \param[out] actor1 a reference to the pointer for the second actor + + @see PxActor + */ + virtual void getActors(PxRigidActor*& actor0, PxRigidActor*& actor1) const = 0; + + /** + \brief Sets the actors for this constraint. + + \param[in] actor0 a reference to the pointer for the first actor + \param[in] actor1 a reference to the pointer for the second actor + + @see PxActor + */ + virtual void setActors(PxRigidActor* actor0, PxRigidActor* actor1) = 0; + + /** + \brief Notify the scene that the constraint shader data has been updated by the application + */ + virtual void markDirty() = 0; + + /** + \brief Set the flags for this constraint + + \param[in] flags the new constraint flags + + default: PxConstraintFlag::eDRIVE_LIMITS_ARE_FORCES + + @see PxConstraintFlags + */ + virtual void setFlags(PxConstraintFlags flags) = 0; + + /** + \brief Retrieve the flags for this constraint + + \return the constraint flags + @see PxConstraintFlags + */ + virtual PxConstraintFlags getFlags() const = 0; + + /** + \brief Set a flag for this constraint + + \param[in] flag the constraint flag + \param[in] value the new value of the flag + + @see PxConstraintFlags + */ + virtual void setFlag(PxConstraintFlag::Enum flag, bool value) = 0; + + /** + \brief Retrieve the constraint force most recently applied to maintain this constraint. + + \param[out] linear the constraint force + \param[out] angular the constraint torque + */ + virtual void getForce(PxVec3& linear, PxVec3& angular) const = 0; + + /** + \brief whether the constraint is valid. + + A constraint is valid if it has at least one dynamic rigid body or articulation link. A constraint that + is not valid may not be inserted into a scene, and therefore a static actor to which an invalid constraint + is attached may not be inserted into a scene. + + Invalid constraints arise only when an actor to which the constraint is attached has been deleted. + */ + virtual bool isValid() const = 0; + + /** + \brief Set the break force and torque thresholds for this constraint. + + If either the force or torque measured at the constraint exceed these thresholds the constraint will break. + + \param[in] linear the linear break threshold + \param[in] angular the angular break threshold + */ + virtual void setBreakForce(PxReal linear, PxReal angular) = 0; + + /** + \brief Retrieve the constraint break force and torque thresholds + + \param[out] linear the linear break threshold + \param[out] angular the angular break threshold + */ + virtual void getBreakForce(PxReal& linear, PxReal& angular) const = 0; + + /** + \brief Set the minimum response threshold for a constraint row + + When using mass modification for a joint or infinite inertia for a jointed body, very stiff solver constraints can be generated which + can destabilize simulation. Setting this value to a small positive value (e.g. 1e-8) will cause constraint rows to be ignored if very + large changes in impulses will generate only small changes in velocity. When setting this value, also set + PxConstraintFlag::eDISABLE_PREPROCESSING. The solver accuracy for this joint may be reduced. + + \param[in] threshold the minimum response threshold + + @see PxConstraintFlag::eDISABLE_PREPROCESSING + */ + virtual void setMinResponseThreshold(PxReal threshold) = 0; + + /** + \brief Retrieve the constraint break force and torque thresholds + + \return the minimum response threshold for a constraint row + */ + virtual PxReal getMinResponseThreshold() const = 0; + + /** + \brief Fetch external owner of the constraint. + + Provides a reference to the external owner of a constraint and a unique owner type ID. + + \param[out] typeID Unique type identifier of the external object. + \return Reference to the external object which owns the constraint. + + @see PxConstraintConnector.getExternalReference() + */ + virtual void* getExternalReference(PxU32& typeID) = 0; + + /** + \brief Set the constraint functions for this constraint + + \param[in] connector the constraint connector object by which the SDK communicates with the constraint. + \param[in] shaders the shader table for the constraint + + @see PxConstraintConnector PxConstraintSolverPrep PxConstraintProject PxConstraintVisualize + */ + virtual void setConstraintFunctions(PxConstraintConnector& connector, + const PxConstraintShaderTable& shaders) = 0; + + virtual const char* getConcreteTypeName() const { return "PxConstraint"; } + +protected: + PX_INLINE PxConstraint(PxType concreteType, PxBaseFlags baseFlags) : PxBase(concreteType, baseFlags) {} + PX_INLINE PxConstraint(PxBaseFlags baseFlags) : PxBase(baseFlags) {} + virtual ~PxConstraint() {} + virtual bool isKindOf(const char* name) const { return !::strcmp("PxConstraint", name) || PxBase::isKindOf(name); } + +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/PxConstraintDesc.h b/sources/PhysX/PhysX/include/PxConstraintDesc.h new file mode 100644 index 00000000..785f5879 --- /dev/null +++ b/sources/PhysX/PhysX/include/PxConstraintDesc.h @@ -0,0 +1,443 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_PHYSICS_NX_CONSTRAINTDESC +#define PX_PHYSICS_NX_CONSTRAINTDESC + +/** \addtogroup physics +@{ +*/ + +#include "PxPhysXConfig.h" +#include "foundation/PxFlags.h" +#include "foundation/PxVec3.h" +#include "common/PxBase.h" + +#if !PX_DOXYGEN +namespace physx { namespace pvdsdk { +#endif + class PvdDataStream; +#if !PX_DOXYGEN +}} +#endif + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxConstraintConnector; +class PxRigidActor; +class PxScene; +class PxConstraintConnector; +class PxRenderBuffer; +class PxDeletionListener; + +/** + \brief constraint row flags + + These flags configure the post-processing of constraint rows and the behavior of the solver while solving constraints +*/ +struct Px1DConstraintFlag +{ + PX_CUDA_CALLABLE Px1DConstraintFlag(){} + + enum Type + { + eSPRING = 1<<0, //!< whether the constraint is a spring. Mutually exclusive with eRESTITUTION. If set, eKEEPBIAS is ignored. + eACCELERATION_SPRING = 1<<1, //!< whether the constraint is a force or acceleration spring. Only valid if eSPRING is set. + eRESTITUTION = 1<<2, //!< whether the restitution model should be applied to generate the target velocity. Mutually exclusive with eSPRING. If restitution causes a bounces, eKEEPBIAS is ignored + eKEEPBIAS = 1<<3, //!< whether to keep the error term when solving for velocity. Ignored if restitution generates bounce, or eSPRING is set. + eOUTPUT_FORCE = 1<<4, //!< whether to accumulate the force value from this constraint in the force total that is reported for the constraint and tested for breakage + eHAS_DRIVE_LIMIT = 1<<5, //!< whether the constraint has a drive force limit (which will be scaled by dt unless PxConstraintFlag::eLIMITS_ARE_FORCES is set) + eANGULAR_CONSTRAINT = 1 << 6,//!< Whether this is an angular or linear constraint + eDRIVE_ROW = 1 << 7 + }; +}; + +typedef PxFlags Px1DConstraintFlags; +PX_FLAGS_OPERATORS(Px1DConstraintFlag::Type, PxU16) + +/** +\brief constraint type hints which the solver uses to optimize constraint handling +*/ +struct PxConstraintSolveHint +{ + enum Enum + { + eNONE = 0, //!< no special properties + eACCELERATION1 = 256, //!< a group of acceleration drive constraints with the same stiffness and drive parameters + eSLERP_SPRING = 258, //!< temporary special value to identify SLERP drive rows + eACCELERATION2 = 512, //!< a group of acceleration drive constraints with the same stiffness and drive parameters + eACCELERATION3 = 768, //!< a group of acceleration drive constraints with the same stiffness and drive parameters + eROTATIONAL_EQUALITY = 1024, //!< rotational equality constraints with no force limit and no velocity target + eROTATIONAL_INEQUALITY = 1025, //!< rotational inequality constraints with (0, PX_MAX_FLT) force limits + eEQUALITY = 2048, //!< equality constraints with no force limit and no velocity target + eINEQUALITY = 2049 //!< inequality constraints with (0, PX_MAX_FLT) force limits + }; +}; + +/** +\brief A constraint + +A constraint is expressed as a set of 1-dimensional constraint rows which define the required constraint +on the objects' velocities. + +Each constraint is either a hard constraint or a spring. We define the velocity at the constraint to be +the quantity + + v = body0vel.dot(lin0,ang0) - body1vel.dot(lin1, ang1) + +For a hard constraint, the solver attempts to generate + +1. a set of velocities for the objects which, when integrated, respect the constraint errors: + + v + (geometricError / timestep) = velocityTarget + +2. a set of velocities for the objects which respect the constraints: + + v = velocityTarget + +Hard constraints support restitution: if the impact velocity exceeds the bounce threshold, then the target velocity +of the constraint will be set to restitution * -v + +Alternatively, the solver can attempt to resolve the velocity constraint as an implicit spring: + + F = stiffness * -geometricError + damping * (velocityTarget - v) + +where F is the constraint force or acceleration. Springs are fully implicit: that is, the force or acceleration +is a function of the position and velocity after the solve. + +All constraints support limits on the minimum or maximum impulse applied. +*/ + +PX_ALIGN_PREFIX(16) +struct Px1DConstraint +{ + PxVec3 linear0; //!< linear component of velocity jacobian in world space + PxReal geometricError; //!< geometric error of the constraint along this axis + PxVec3 angular0; //!< angular component of velocity jacobian in world space + PxReal velocityTarget; //!< velocity target for the constraint along this axis + + PxVec3 linear1; //!< linear component of velocity jacobian in world space + PxReal minImpulse; //!< minimum impulse the solver may apply to enforce this constraint + PxVec3 angular1; //!< angular component of velocity jacobian in world space + PxReal maxImpulse; //!< maximum impulse the solver may apply to enforce this constraint + + union + { + struct SpringModifiers + { + PxReal stiffness; //!< spring parameter, for spring constraints + PxReal damping; //!< damping parameter, for spring constraints + } spring; + struct RestitutionModifiers + { + PxReal restitution; //!< restitution parameter for determining additional "bounce" + PxReal velocityThreshold; //!< minimum impact velocity for bounce + } bounce; + } mods; + + PxReal forInternalUse; //!< for internal use only + PxU16 flags; //!< a set of Px1DConstraintFlags + PxU16 solveHint; //!< constraint optimization hint, should be an element of PxConstraintSolveHint +} +PX_ALIGN_SUFFIX(16); + + +/** +\brief Flags for determining which components of the constraint should be visualized. + +@see PxConstraintVisualize +*/ +struct PxConstraintVisualizationFlag +{ + enum Enum + { + eLOCAL_FRAMES = 1, //!< visualize constraint frames + eLIMITS = 2 //!< visualize constraint limits + }; +}; + +PX_ALIGN_PREFIX(16) +struct PxConstraintInvMassScale +{ +//= ATTENTION! ===================================================================================== +// Changing the data layout of this class breaks the binary serialization format. See comments for +// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData +// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION +// accordingly. +//================================================================================================== + + PxReal linear0; //!< multiplier for inverse mass of body0 + PxReal angular0; //!< multiplier for inverse MoI of body0 + PxReal linear1; //!< multiplier for inverse mass of body1 + PxReal angular1; //!< multiplier for inverse MoI of body1 + + PX_CUDA_CALLABLE PX_FORCE_INLINE PxConstraintInvMassScale(){} + PX_CUDA_CALLABLE PX_FORCE_INLINE PxConstraintInvMassScale(PxReal lin0, PxReal ang0, PxReal lin1, PxReal ang1) : linear0(lin0), angular0(ang0), linear1(lin1), angular1(ang1){} +} +PX_ALIGN_SUFFIX(16); + +/** solver constraint generation shader + +This function is called by the constraint solver framework. The function must be reentrant, since it may be called simultaneously +from multiple threads, and should access only the arguments passed into it. + +Developers writing custom constraints are encouraged to read the documentation in the user guide and the implementation code in PhysXExtensions. + +\param[out] constraints An array of solver constraint rows to be filled in +\param[out] bodyAWorldOffset The origin point (offset from the position vector of bodyA's center of mass) at which the constraint is resolved. This value does not affect how constraints are solved, only the constraint force reported. +\param[in] maxConstraints The size of the constraint buffer. At most this many constraints rows may be written +\param[out] invMassScale The inverse mass and inertia scales for the constraint +\param[in] constantBlock The constant data block +\param[in] bodyAToWorld The center of mass frame of the first constrained body (the identity transform if the first actor is static, or if a NULL actor pointer was provided for it) +\param[in] bodyBToWorld The center of mass frame of the second constrained body (the identity transform if the second actor is static, or if a NULL actor pointer was provided for it) +\param[in] useExtendedLimits Enables limit ranges outside of (-PI, PI) +\param[out] cAtW The world space location of body A's joint frame (position only) +\param[out] cBtW The world space location of body B's joint frame (position only) + +\return the number of constraint rows written. +*/ +typedef PxU32 (*PxConstraintSolverPrep)(Px1DConstraint* constraints, + PxVec3& bodyAWorldOffset, + PxU32 maxConstraints, + PxConstraintInvMassScale& invMassScale, + const void* constantBlock, + const PxTransform& bodyAToWorld, + const PxTransform& bodyBToWorld, + bool useExtendedLimits, + PxVec3& cAtW, + PxVec3& cBtW); + +/** solver constraint projection shader + +This function is called by the constraint post-solver framework. The function must be reentrant, since it may be called simultaneously +from multiple threads and should access only the arguments passed into it. + +\param[in] constantBlock The constant data block +\param[out] bodyAToWorld The center of mass frame of the first constrained body (the identity if the actor is static or a NULL pointer was provided for it) +\param[out] bodyBToWorld The center of mass frame of the second constrained body (the identity if the actor is static or a NULL pointer was provided for it) +\param[in] projectToA True if the constraint should be projected by moving the second body towards the first, false if the converse +*/ +typedef void (*PxConstraintProject)(const void* constantBlock, + PxTransform& bodyAToWorld, + PxTransform& bodyBToWorld, + bool projectToA); + +/** + API used to visualize details about a constraint. +*/ +class PxConstraintVisualizer +{ +protected: + virtual ~PxConstraintVisualizer(){} +public: + /** Visualize joint frames + + \param[in] parent Parent transformation + \param[in] child Child transformation + */ + virtual void visualizeJointFrames(const PxTransform& parent, const PxTransform& child) = 0; + + /** Visualize joint linear limit + + \param[in] t0 Base transformation + \param[in] t1 End transformation + \param[in] value Distance + \param[in] active State of the joint - active/inactive + */ + virtual void visualizeLinearLimit(const PxTransform& t0, const PxTransform& t1, PxReal value, bool active) = 0; + + /** Visualize joint angular limit + + \param[in] t0 Transformation for the visualization + \param[in] lower Lower limit angle + \param[in] upper Upper limit angle + \param[in] active State of the joint - active/inactive + */ + virtual void visualizeAngularLimit(const PxTransform& t0, PxReal lower, PxReal upper, bool active) = 0; + + /** Visualize limit cone + + \param[in] t Transformation for the visualization + \param[in] tanQSwingY Tangent of the quarter Y angle + \param[in] tanQSwingZ Tangent of the quarter Z angle + \param[in] active State of the joint - active/inactive + */ + virtual void visualizeLimitCone(const PxTransform& t, PxReal tanQSwingY, PxReal tanQSwingZ, bool active) = 0; + + /** Visualize joint double cone + + \param[in] t Transformation for the visualization + \param[in] angle Limit angle + \param[in] active State of the joint - active/inactive + */ + virtual void visualizeDoubleCone(const PxTransform& t, PxReal angle, bool active) = 0; + + /** Visualize line + + \param[in] p0 Start position + \param[in] p1 End postion + \param[in] color Color + */ + virtual void visualizeLine(const PxVec3& p0, const PxVec3& p1, PxU32 color) = 0; +}; + +/** solver constraint visualization function + +This function is called by the constraint post-solver framework to visualize the constraint + +\param[out] visualizer The render buffer to render to +\param[in] constantBlock The constant data block +\param[in] body0Transform The center of mass frame of the first constrained body (the identity if the actor is static, or a NULL pointer was provided for it) +\param[in] body1Transform The center of mass frame of the second constrained body (the identity if the actor is static, or a NULL pointer was provided for it) +\param[in] flags The visualization flags (PxConstraintVisualizationFlag) + +@see PxRenderBuffer +*/ +typedef void (*PxConstraintVisualize)(PxConstraintVisualizer& visualizer, + const void* constantBlock, + const PxTransform& body0Transform, + const PxTransform& body1Transform, + PxU32 flags); + + +struct PxPvdUpdateType +{ + enum Enum + { + CREATE_INSTANCE, + RELEASE_INSTANCE, + UPDATE_ALL_PROPERTIES, + UPDATE_SIM_PROPERTIES + }; +}; + +/** + +\brief This class connects a custom constraint to the SDK + +This class connects a custom constraint to the SDK, and functions are called by the SDK +to query the custom implementation for specific information to pass on to the application +or inform the constraint when the application makes calls into the SDK which will update +the custom constraint's internal implementation +*/ +class PxConstraintConnector +{ +public: + /** + when the constraint is marked dirty, this function is called at the start of the simulation + step for the SDK to copy the constraint data block. + */ + virtual void* prepareData() = 0; + + /** + this function is called by the SDK to update PVD's view of it + */ + virtual bool updatePvdProperties(physx::pvdsdk::PvdDataStream& pvdConnection, + const PxConstraint* c, + PxPvdUpdateType::Enum updateType) const = 0; + + /** + When the SDK deletes a PxConstraint object this function is called by the SDK. In general + custom constraints should not be deleted directly by applications: rather, the constraint + should respond to a release() request by calling PxConstraint::release(), then wait for + this call to release its own resources, so that even if the release() call occurs during + a simulation step, the deletion of the constraint is buffered until that step completes. + + This function is also called when a PxConstraint object is deleted on cleanup due to + destruction of the PxPhysics object. + */ + virtual void onConstraintRelease() = 0; + + /** + This function is called by the SDK when the CoM of one of the actors is moved. Since the + API specifies constraint positions relative to actors, and the constraint shader functions + are supplied with coordinates relative to bodies, some synchronization is usually required + when the application moves an object's center of mass. + */ + virtual void onComShift(PxU32 actor) = 0; + + /** + This function is called by the SDK when the scene origin gets shifted and allows to adjust + custom data which contains world space transforms. + + \note If the adjustments affect constraint shader data, it is necessary to call PxConstraint::markDirty() + to make sure that the data gets synced at the beginning of the next simulation step. + + \param[in] shift Translation vector the origin is shifted by. + + @see PxScene.shiftOrigin() + */ + virtual void onOriginShift(const PxVec3& shift) = 0; + + /** + \brief Fetches external data for a constraint. + + This function is used by the SDK to acquire a reference to the owner of a constraint and a unique + owner type ID. This information will be passed on when a breakable constraint breaks or when + #PxConstraint::getExternalReference() is called. + + \param[out] typeID Unique type identifier of the external object. The value 0xffffffff is reserved and should not be used. Furthermore, if the PhysX extensions library is used, some other IDs are reserved already (see PxConstraintExtIDs) + \return Reference to the external object which owns the constraint. + + @see PxConstraintInfo PxSimulationEventCallback.onConstraintBreak() + */ + virtual void* getExternalReference(PxU32& typeID) = 0; + + /** + \brief Obtain a reference to a PxBase interface if the constraint has one. + + If the constraint does not implement the PxBase interface, it should return NULL. + */ + virtual PxBase* getSerializable() = 0; + + /** + \brief Obtain the shader function pointer used to prep rows for this constraint + */ + virtual PxConstraintSolverPrep getPrep() const = 0; + + /** + \brief Obtain the pointer to the constraint's constant data + */ + virtual const void* getConstantBlock() const = 0; + + /** + \brief virtual destructor + */ + virtual ~PxConstraintConnector() {} +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/PxContact.h b/sources/PhysX/PhysX/include/PxContact.h new file mode 100644 index 00000000..4d85f59a --- /dev/null +++ b/sources/PhysX/PhysX/include/PxContact.h @@ -0,0 +1,583 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_CONTACT_H +#define PX_CONTACT_H + +#include "foundation/PxVec3.h" +#include "foundation/PxAssert.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +#if PX_VC +#pragma warning(push) +#pragma warning(disable: 4324) // Padding was added at the end of a structure because of a __declspec(align) value. +#endif + +#define PXC_CONTACT_NO_FACE_INDEX 0xffffffff + +PX_ALIGN_PREFIX(16) +struct PxMassModificationProps +{ + PxReal mInvMassScale0; + PxReal mInvInertiaScale0; + PxReal mInvMassScale1; + PxReal mInvInertiaScale1; +} +PX_ALIGN_SUFFIX(16); + +/** +\brief Header for contact patch where all points share same material and normal +*/ + +PX_ALIGN_PREFIX(16) +struct PxContactPatch +{ + enum PxContactPatchFlags + { + eHAS_FACE_INDICES = 1, //!< Indicates this contact stream has face indices. + eMODIFIABLE = 2, //!< Indicates this contact stream is modifiable. + eFORCE_NO_RESPONSE = 4, //!< Indicates this contact stream is notify-only (no contact response). + eHAS_MODIFIED_MASS_RATIOS = 8, //!< Indicates this contact stream has modified mass ratios + eHAS_TARGET_VELOCITY = 16, //!< Indicates this contact stream has target velocities set + eHAS_MAX_IMPULSE = 32, //!< Indicates this contact stream has max impulses set + eREGENERATE_PATCHES = 64, //!< Indicates this contact stream needs patches re-generated. + //!< This is required if the application modified either the contact normal or the material properties + eCOMPRESSED_MODIFIED_CONTACT = 128 + }; + + PX_ALIGN(16, PxMassModificationProps mMassModification); //16 + /** + \brief Contact normal + */ + PX_ALIGN(16, PxVec3 normal); //28 + /** + \brief Restitution coefficient + */ + PxReal restitution; //32 + + PxReal dynamicFriction; //36 + PxReal staticFriction; //40 + PxU8 startContactIndex; //41 + PxU8 nbContacts; //42 //Can be a U8 + + PxU8 materialFlags; //43 //Can be a U16 + PxU8 internalFlags; //44 //Can be a U16 + PxU16 materialIndex0; //46 //Can be a U16 + PxU16 materialIndex1; //48 //Can be a U16 + + +} +PX_ALIGN_SUFFIX(16); + +/** +\brief Contact point data including face (feature) indices +*/ + +PX_ALIGN_PREFIX(16) +struct PxContact +{ + /** + \brief Contact point in world space + */ + PxVec3 contact; //12 + /** + \brief Separation value (negative implies penetration). + */ + PxReal separation; //16 +} +PX_ALIGN_SUFFIX(16); + +PX_ALIGN_PREFIX(16) +struct PxExtendedContact : public PxContact +{ + /** + \brief Target velocity + */ + PX_ALIGN(16, PxVec3 targetVelocity); //28 + /** + \brief Maximum impulse + */ + PxReal maxImpulse; //32 +} +PX_ALIGN_SUFFIX(16); + +/** +\brief A modifiable contact point. This has additional fields per-contact to permit modification by user. +\note Not all fields are currently exposed to the user. +*/ +PX_ALIGN_PREFIX(16) +struct PxModifiableContact : public PxExtendedContact +{ + /** + \brief Contact normal + */ + PX_ALIGN(16, PxVec3 normal); //44 + /** + \brief Restitution coefficient + */ + PxReal restitution; //48 + + /** + \brief Material Flags + */ + PxU32 materialFlags; //52 + + /** + \brief Shape A's material index + */ + PxU16 materialIndex0; //54 + /** + \brief Shape B's material index + */ + PxU16 materialIndex1; //56 + /** + \brief static friction coefficient + */ + PxReal staticFriction; //60 + /** + \brief dynamic friction coefficient + */ + PxReal dynamicFriction; //64 +} +PX_ALIGN_SUFFIX(16); + +/** +\brief A class to iterate over a compressed contact stream. This supports read-only access to the various contact formats. +*/ +struct PxContactStreamIterator +{ + enum StreamFormat + { + eSIMPLE_STREAM, + eMODIFIABLE_STREAM, + eCOMPRESSED_MODIFIABLE_STREAM + }; + /** + \brief Utility zero vector to optimize functions returning zero vectors when a certain flag isn't set. + \note This allows us to return by reference instead of having to return by value. Returning by value will go via memory (registers -> stack -> registers), which can + cause performance issues on certain platforms. + */ + PxVec3 zero; + /** + \brief The patch headers. + */ + const PxContactPatch* patch; + + /** + \brief The contacts + */ + const PxContact* contact; + + /** + \brief The contact triangle face index + */ + const PxU32* faceIndice; + + + /** + \brief The total number of patches in this contact stream + */ + PxU32 totalPatches; + + /** + \brief The total number of contact points in this stream + */ + PxU32 totalContacts; + + /** + \brief The current contact index + */ + PxU32 nextContactIndex; + + /** + \brief The current patch Index + */ + PxU32 nextPatchIndex; + + /* + \brief Size of contact patch header + \note This varies whether the patch is modifiable or not. + */ + PxU32 contactPatchHeaderSize; + /** + \brief Contact point size + \note This varies whether the patch has feature indices or is modifiable. + */ + PxU32 contactPointSize; + /** + \brief The stream format + */ + StreamFormat mStreamFormat; + /** + \brief Indicates whether this stream is notify-only or not. + */ + PxU32 forceNoResponse; + + bool pointStepped; + + PxU32 hasFaceIndices; + + /** + \brief Constructor + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxContactStreamIterator(const PxU8* contactPatches, const PxU8* contactPoints, const PxU32* contactFaceIndices, PxU32 nbPatches, PxU32 nbContacts) + : zero(0.f) + { + bool modify = false; + bool compressedModify = false; + bool response = false; + bool indices = false; + + PxU32 pointSize = 0; + PxU32 patchHeaderSize = sizeof(PxContactPatch); + + const PxContactPatch* patches = reinterpret_cast(contactPatches); + + if(patches) + { + modify = (patches->internalFlags & PxContactPatch::eMODIFIABLE) != 0; + compressedModify = (patches->internalFlags & PxContactPatch::eCOMPRESSED_MODIFIED_CONTACT) != 0; + indices = (patches->internalFlags & PxContactPatch::eHAS_FACE_INDICES) != 0; + + patch = patches; + + contact = reinterpret_cast(contactPoints); + + faceIndice = contactFaceIndices; + + pointSize = compressedModify ? sizeof(PxExtendedContact) : modify ? sizeof(PxModifiableContact) : sizeof(PxContact); + + response = (patch->internalFlags & PxContactPatch::eFORCE_NO_RESPONSE) == 0; + } + + + mStreamFormat = compressedModify ? eCOMPRESSED_MODIFIABLE_STREAM : modify ? eMODIFIABLE_STREAM : eSIMPLE_STREAM; + hasFaceIndices = PxU32(indices); + forceNoResponse = PxU32(!response); + + contactPatchHeaderSize = patchHeaderSize; + contactPointSize = pointSize; + nextPatchIndex = 0; + nextContactIndex = 0; + totalContacts = nbContacts; + totalPatches = nbPatches; + + pointStepped = false; + } + + /** + \brief Returns whether there are more patches in this stream. + \return Whether there are more patches in this stream. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE bool hasNextPatch() const + { + return nextPatchIndex < totalPatches; + } + + /** + \brief Returns the total contact count. + \return Total contact count. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 getTotalContactCount() const + { + return totalContacts; + } + + PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 getTotalPatchCount() const + { + return totalPatches; + } + + /** + \brief Advances iterator to next contact patch. + */ + PX_CUDA_CALLABLE PX_INLINE void nextPatch() + { + PX_ASSERT(nextPatchIndex < totalPatches); + if(nextPatchIndex) + { + if(nextContactIndex < patch->nbContacts) + { + PxU32 nbToStep = patch->nbContacts - this->nextContactIndex; + contact = reinterpret_cast(reinterpret_cast(contact) + contactPointSize * nbToStep); + } + patch = reinterpret_cast(reinterpret_cast(patch) + contactPatchHeaderSize); + } + nextPatchIndex++; + nextContactIndex = 0; + } + + /** + \brief Returns if the current patch has more contacts. + \return If there are more contacts in the current patch. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE bool hasNextContact() const + { + return nextContactIndex < (patch->nbContacts); + } + + /** + \brief Advances to the next contact in the patch. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE void nextContact() + { + PX_ASSERT(nextContactIndex < patch->nbContacts); + if(pointStepped) + { + contact = reinterpret_cast(reinterpret_cast(contact) + contactPointSize); + faceIndice++; + } + nextContactIndex++; + pointStepped = true; + } + + + /** + \brief Gets the current contact's normal + \return The current contact's normal. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE const PxVec3& getContactNormal() const + { + return getContactPatch().normal; + } + + /** + \brief Gets the inverse mass scale for body 0. + \return The inverse mass scale for body 0. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getInvMassScale0() const + { + return patch->mMassModification.mInvMassScale0; + } + + /** + \brief Gets the inverse mass scale for body 1. + \return The inverse mass scale for body 1. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getInvMassScale1() const + { + return patch->mMassModification.mInvMassScale1; + } + + /** + \brief Gets the inverse inertia scale for body 0. + \return The inverse inertia scale for body 0. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getInvInertiaScale0() const + { + return patch->mMassModification.mInvInertiaScale0; + } + + /** + \brief Gets the inverse inertia scale for body 1. + \return The inverse inertia scale for body 1. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getInvInertiaScale1() const + { + return patch->mMassModification.mInvInertiaScale1; + } + + /** + \brief Gets the contact's max impulse. + \return The contact's max impulse. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getMaxImpulse() const + { + return mStreamFormat != eSIMPLE_STREAM ? getExtendedContact().maxImpulse : PX_MAX_REAL; + } + + /** + \brief Gets the contact's target velocity. + \return The contact's target velocity. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE const PxVec3& getTargetVel() const + { + return mStreamFormat != eSIMPLE_STREAM ? getExtendedContact().targetVelocity : zero; + } + + /** + \brief Gets the contact's contact point. + \return The contact's contact point. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE const PxVec3& getContactPoint() const + { + return contact->contact; + } + + /** + \brief Gets the contact's separation. + \return The contact's separation. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getSeparation() const + { + return contact->separation; + } + + /** + \brief Gets the contact's face index for shape 0. + \return The contact's face index for shape 0. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 getFaceIndex0() const + { + return PXC_CONTACT_NO_FACE_INDEX; + } + + /** + \brief Gets the contact's face index for shape 1. + \return The contact's face index for shape 1. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 getFaceIndex1() const + { + return hasFaceIndices ? *faceIndice : PXC_CONTACT_NO_FACE_INDEX; + } + + /** + \brief Gets the contact's static friction coefficient. + \return The contact's static friction coefficient. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getStaticFriction() const + { + return getContactPatch().staticFriction; + } + + /** + \brief Gets the contact's static dynamic coefficient. + \return The contact's static dynamic coefficient. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getDynamicFriction() const + { + return getContactPatch().dynamicFriction; + } + + /** + \brief Gets the contact's restitution coefficient. + \return The contact's restitution coefficient. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getRestitution() const + { + return getContactPatch().restitution; + } + + /** + \brief Gets the contact's material flags. + \return The contact's material flags. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 getMaterialFlags() const + { + return getContactPatch().materialFlags; + } + + /** + \brief Gets the contact's material index for shape 0. + \return The contact's material index for shape 0. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxU16 getMaterialIndex0() const + { + return PxU16(getContactPatch().materialIndex0); + } + + /** + \brief Gets the contact's material index for shape 1. + \return The contact's material index for shape 1. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxU16 getMaterialIndex1() const + { + return PxU16(getContactPatch().materialIndex1); + } + + /** + \brief Advances the contact stream iterator to a specific contact index. + */ + bool advanceToIndex(const PxU32 initialIndex) + { + PX_ASSERT(this->nextPatchIndex == 0 && this->nextContactIndex == 0); + + PxU32 numToAdvance = initialIndex; + + if(numToAdvance == 0) + { + PX_ASSERT(hasNextPatch()); + nextPatch(); + return true; + } + + while(numToAdvance) + { + while(hasNextPatch()) + { + nextPatch(); + PxU32 patchSize = patch->nbContacts; + if(numToAdvance <= patchSize) + { + contact = reinterpret_cast(reinterpret_cast(contact) + contactPointSize * numToAdvance); + nextContactIndex += numToAdvance; + return true; + } + else + { + numToAdvance -= patchSize; + } + } + } + return false; + } + +private: + + /** + \brief Internal helper + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE const PxContactPatch& getContactPatch() const + { + return *static_cast(patch); + } + + PX_CUDA_CALLABLE PX_FORCE_INLINE const PxExtendedContact& getExtendedContact() const + { + PX_ASSERT(mStreamFormat == eMODIFIABLE_STREAM || mStreamFormat == eCOMPRESSED_MODIFIABLE_STREAM); + return *static_cast(contact); + } + +}; + + +#if PX_VC +#pragma warning(pop) +#endif + +#if !PX_DOXYGEN +} // namespace physx +#endif + +#endif diff --git a/sources/PhysX/PhysX/include/PxContactModifyCallback.h b/sources/PhysX/PhysX/include/PxContactModifyCallback.h new file mode 100644 index 00000000..bb3bb58f --- /dev/null +++ b/sources/PhysX/PhysX/include/PxContactModifyCallback.h @@ -0,0 +1,486 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_CONTACT_MODIFY_CALLBACK +#define PX_CONTACT_MODIFY_CALLBACK +/** \addtogroup physics +@{ +*/ + +#include "PxPhysXConfig.h" +#include "PxShape.h" +#include "PxContact.h" +#include "foundation/PxTransform.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxShape; + +/** +\brief An array of contact points, as passed to contact modification. + +The word 'set' in the name does not imply that duplicates are filtered in any +way. This initial set of contacts does potentially get reduced to a smaller +set before being passed to the solver. + +You can use the accessors to read and write contact properties. The number of +contacts is immutable, other than being able to disable contacts using ignore(). + +@see PxContactModifyCallback, PxModifiableContact +*/ +class PxContactSet +{ +public: + /** + \brief Get the position of a specific contact point in the set. + + @see PxModifiableContact.point + */ + PX_FORCE_INLINE const PxVec3& getPoint(PxU32 i) const { return mContacts[i].contact; } + + /** + \brief Alter the position of a specific contact point in the set. + + @see PxModifiableContact.point + */ + PX_FORCE_INLINE void setPoint(PxU32 i, const PxVec3& p) { mContacts[i].contact = p; } + + /** + \brief Get the contact normal of a specific contact point in the set. + + @see PxModifiableContact.normal + */ + PX_FORCE_INLINE const PxVec3& getNormal(PxU32 i) const { return mContacts[i].normal; } + + /** + \brief Alter the contact normal of a specific contact point in the set. + + \note Changing the normal can cause contact points to be ignored. + + @see PxModifiableContact.normal + */ + PX_FORCE_INLINE void setNormal(PxU32 i, const PxVec3& n) + { + PxContactPatch* patch = getPatch(); + patch->internalFlags |= PxContactPatch::eREGENERATE_PATCHES; + mContacts[i].normal = n; + } + + /** + \brief Get the separation of a specific contact point in the set. + + @see PxModifiableContact.separation + */ + PX_FORCE_INLINE PxReal getSeparation(PxU32 i) const { return mContacts[i].separation; } + + /** + \brief Alter the separation of a specific contact point in the set. + + @see PxModifiableContact.separation + */ + PX_FORCE_INLINE void setSeparation(PxU32 i, PxReal s) { mContacts[i].separation = s; } + + /** + \brief Get the target velocity of a specific contact point in the set. + + @see PxModifiableContact.targetVelocity + + */ + PX_FORCE_INLINE const PxVec3& getTargetVelocity(PxU32 i) const { return mContacts[i].targetVelocity; } + + /** + \brief Alter the target velocity of a specific contact point in the set. + + @see PxModifiableContact.targetVelocity + */ + PX_FORCE_INLINE void setTargetVelocity(PxU32 i, const PxVec3& v) + { + PxContactPatch* patch = getPatch(); + patch->internalFlags |= PxContactPatch::eHAS_TARGET_VELOCITY; + mContacts[i].targetVelocity = v; + } + + /** + \brief Get the face index with respect to the first shape of the pair for a specific contact point in the set. + + @see PxModifiableContact.internalFaceIndex0 + */ + PX_FORCE_INLINE PxU32 getInternalFaceIndex0(PxU32 i) { PX_UNUSED(i); return PXC_CONTACT_NO_FACE_INDEX; } + + /** + \brief Get the face index with respect to the second shape of the pair for a specific contact point in the set. + + @see PxModifiableContact.internalFaceIndex1 + */ + PX_FORCE_INLINE PxU32 getInternalFaceIndex1(PxU32 i) + { + PxContactPatch* patch = getPatch(); + if (patch->internalFlags & PxContactPatch::eHAS_FACE_INDICES) + { + return reinterpret_cast(mContacts + mCount)[mCount + i]; + } + return PXC_CONTACT_NO_FACE_INDEX; + } + + /** + \brief Get the maximum impulse for a specific contact point in the set. + + @see PxModifiableContact.maxImpulse + */ + PX_FORCE_INLINE PxReal getMaxImpulse(PxU32 i) const { return mContacts[i].maxImpulse; } + + /** + \brief Alter the maximum impulse for a specific contact point in the set. + + \note Must be nonnegative. If set to zero, the contact point will be ignored + + @see PxModifiableContact.maxImpulse + */ + PX_FORCE_INLINE void setMaxImpulse(PxU32 i, PxReal s) + { + PxContactPatch* patch = getPatch(); + patch->internalFlags |= PxContactPatch::eHAS_MAX_IMPULSE; + mContacts[i].maxImpulse = s; + } + + /** + \brief Get the restitution coefficient for a specific contact point in the set. + + @see PxModifiableContact.restitution + */ + PX_FORCE_INLINE PxReal getRestitution(PxU32 i) const { return mContacts[i].restitution; } + + /** + \brief Alter the restitution coefficient for a specific contact point in the set. + + \note Valid ranges [0,1] + + @see PxModifiableContact.restitution + */ + PX_FORCE_INLINE void setRestitution(PxU32 i, PxReal r) + { + PxContactPatch* patch = getPatch(); + patch->internalFlags |= PxContactPatch::eREGENERATE_PATCHES; + mContacts[i].restitution = r; + } + + /** + \brief Get the static friction coefficient for a specific contact point in the set. + + @see PxModifiableContact.staticFriction + */ + PX_FORCE_INLINE PxReal getStaticFriction(PxU32 i) const { return mContacts[i].staticFriction; } + + /** + \brief Alter the static friction coefficient for a specific contact point in the set. + + @see PxModifiableContact.staticFriction + */ + PX_FORCE_INLINE void setStaticFriction(PxU32 i, PxReal f) + { + PxContactPatch* patch = getPatch(); + patch->internalFlags |= PxContactPatch::eREGENERATE_PATCHES; + mContacts[i].staticFriction = f; + } + + /** + \brief Get the static friction coefficient for a specific contact point in the set. + + @see PxModifiableContact.dynamicFriction + */ + PX_FORCE_INLINE PxReal getDynamicFriction(PxU32 i) const { return mContacts[i].dynamicFriction; } + + /** + \brief Alter the static dynamic coefficient for a specific contact point in the set. + + @see PxModifiableContact.dynamic + */ + PX_FORCE_INLINE void setDynamicFriction(PxU32 i, PxReal f) + { + PxContactPatch* patch = getPatch(); + patch->internalFlags |= PxContactPatch::eREGENERATE_PATCHES; + mContacts[i].dynamicFriction = f; + } + + /** + \brief Ignore the contact point. + + If a contact point is ignored then no force will get applied at this point. This can be used to disable collision in certain areas of a shape, for example. + */ + PX_FORCE_INLINE void ignore(PxU32 i) { mContacts[i].maxImpulse = 0.f; } + + /** + \brief The number of contact points in the set. + */ + PX_FORCE_INLINE PxU32 size() const { return mCount; } + + /** + \brief Returns the invMassScale of body 0 + + A value < 1.0 makes this contact treat the body as if it had larger mass. A value of 0.f makes this contact + treat the body as if it had infinite mass. Any value > 1.f makes this contact treat the body as if it had smaller mass. + */ + PX_FORCE_INLINE PxReal getInvMassScale0() const + { + PxContactPatch* patch = getPatch(); + return patch->mMassModification.mInvMassScale0; + } + + /** + \brief Returns the invMassScale of body 1 + + A value < 1.0 makes this contact treat the body as if it had larger mass. A value of 0.f makes this contact + treat the body as if it had infinite mass. Any value > 1.f makes this contact treat the body as if it had smaller mass. + */ + PX_FORCE_INLINE PxReal getInvMassScale1() const + { + PxContactPatch* patch = getPatch(); + return patch->mMassModification.mInvMassScale1; + } + + /** + \brief Returns the invInertiaScale of body 0 + + A value < 1.0 makes this contact treat the body as if it had larger inertia. A value of 0.f makes this contact + treat the body as if it had infinite inertia. Any value > 1.f makes this contact treat the body as if it had smaller inertia. + */ + PX_FORCE_INLINE PxReal getInvInertiaScale0() const + { + PxContactPatch* patch = getPatch(); + return patch->mMassModification.mInvInertiaScale0; + } + + /** + \brief Returns the invInertiaScale of body 1 + + A value < 1.0 makes this contact treat the body as if it had larger inertia. A value of 0.f makes this contact + treat the body as if it had infinite inertia. Any value > 1.f makes this contact treat the body as if it had smaller inertia. + */ + PX_FORCE_INLINE PxReal getInvInertiaScale1() const + { + PxContactPatch* patch = getPatch(); + return patch->mMassModification.mInvInertiaScale1; + } + + /** + \brief Sets the invMassScale of body 0 + + This can be set to any value in the range [0, PX_MAX_F32). A value < 1.0 makes this contact treat the body as if it had larger mass. A value of 0.f makes this contact + treat the body as if it had infinite mass. Any value > 1.f makes this contact treat the body as if it had smaller mass. + */ + PX_FORCE_INLINE void setInvMassScale0(const PxReal scale) + { + PxContactPatch* patch = getPatch(); + patch->mMassModification.mInvMassScale0 = scale; + patch->internalFlags |= PxContactPatch::eHAS_MODIFIED_MASS_RATIOS; + } + + /** + \brief Sets the invMassScale of body 1 + + This can be set to any value in the range [0, PX_MAX_F32). A value < 1.0 makes this contact treat the body as if it had larger mass. A value of 0.f makes this contact + treat the body as if it had infinite mass. Any value > 1.f makes this contact treat the body as if it had smaller mass. + */ + PX_FORCE_INLINE void setInvMassScale1(const PxReal scale) + { + PxContactPatch* patch = getPatch(); + patch->mMassModification.mInvMassScale1 = scale; + patch->internalFlags |= PxContactPatch::eHAS_MODIFIED_MASS_RATIOS; + } + + /** + \brief Sets the invInertiaScale of body 0 + + This can be set to any value in the range [0, PX_MAX_F32). A value < 1.0 makes this contact treat the body as if it had larger inertia. A value of 0.f makes this contact + treat the body as if it had infinite inertia. Any value > 1.f makes this contact treat the body as if it had smaller inertia. + */ + PX_FORCE_INLINE void setInvInertiaScale0(const PxReal scale) + { + PxContactPatch* patch = getPatch(); + patch->mMassModification.mInvInertiaScale0 = scale; + patch->internalFlags |= PxContactPatch::eHAS_MODIFIED_MASS_RATIOS; + } + + /** + \brief Sets the invInertiaScale of body 1 + + This can be set to any value in the range [0, PX_MAX_F32). A value < 1.0 makes this contact treat the body as if it had larger inertia. A value of 0.f makes this contact + treat the body as if it had infinite inertia. Any value > 1.f makes this contact treat the body as if it had smaller inertia. + */ + PX_FORCE_INLINE void setInvInertiaScale1(const PxReal scale) + { + PxContactPatch* patch = getPatch(); + patch->mMassModification.mInvInertiaScale1 = scale; + patch->internalFlags |= PxContactPatch::eHAS_MODIFIED_MASS_RATIOS; + } + +protected: + + PX_FORCE_INLINE PxContactPatch* getPatch() const + { + const size_t headerOffset = sizeof(PxContactPatch)*mCount; + return reinterpret_cast(reinterpret_cast(mContacts) - headerOffset); + } + + PxU32 mCount; //!< Number of contact points in the set + PxModifiableContact* mContacts; //!< The contact points of the set +}; + + + +/** +\brief An array of instances of this class is passed to PxContactModifyCallback::onContactModify(). + +@see PxContactModifyCallback +*/ + +class PxContactModifyPair +{ +public: + + /** + \brief The actors which make up the pair in contact. + + Note that these are the actors as seen by the simulation, and may have been deleted since the simulation step started. + */ + + const PxRigidActor* actor[2]; + /** + \brief The shapes which make up the pair in contact. + + Note that these are the shapes as seen by the simulation, and may have been deleted since the simulation step started. + */ + + const PxShape* shape[2]; + + /** + \brief The shape to world transforms of the two shapes. + + These are the transforms as the simulation engine sees them, and may have been modified by the application + since the simulation step started. + + */ + + PxTransform transform[2]; + + /** + \brief An array of contact points between these two shapes. + */ + + PxContactSet contacts; +}; + + +/** +\brief An interface class that the user can implement in order to modify contact constraints. + +Threading: It is necessary to make this class thread safe as it will be called in the context of the +simulation thread. It might also be necessary to make it reentrant, since some calls can be made by multi-threaded +parts of the physics engine. + +You can enable the use of this contact modification callback by raising the flag PxPairFlag::eMODIFY_CONTACTS in +the filter shader/callback (see #PxSimulationFilterShader) for a pair of rigid body objects. + +Please note: ++ Raising the contact modification flag will not wake the actors up automatically. ++ It is not possible to turn off the performance degradation by simply removing the callback from the scene, the + filter shader/callback has to be used to clear the contact modification flag. ++ The contacts will only be reported as long as the actors are awake. There will be no callbacks while the actors are sleeping. + +@see PxScene.setContactModifyCallback() PxScene.getContactModifyCallback() +*/ +class PxContactModifyCallback +{ +public: + + /** + \brief Passes modifiable arrays of contacts to the application. + + The initial contacts are as determined fresh each frame by collision detection. + + The number of contacts can not be changed, so you cannot add your own contacts. You may however + disable contacts using PxContactSet::ignore(). + + @see PxContactModifyPair + */ + virtual void onContactModify(PxContactModifyPair* const pairs, PxU32 count) = 0; + +protected: + virtual ~PxContactModifyCallback(){} +}; + +/** +\brief An interface class that the user can implement in order to modify CCD contact constraints. + +Threading: It is necessary to make this class thread safe as it will be called in the context of the +simulation thread. It might also be necessary to make it reentrant, since some calls can be made by multi-threaded +parts of the physics engine. + +You can enable the use of this contact modification callback by raising the flag PxPairFlag::eMODIFY_CONTACTS in +the filter shader/callback (see #PxSimulationFilterShader) for a pair of rigid body objects. + +Please note: ++ Raising the contact modification flag will not wake the actors up automatically. ++ It is not possible to turn off the performance degradation by simply removing the callback from the scene, the + filter shader/callback has to be used to clear the contact modification flag. ++ The contacts will only be reported as long as the actors are awake. There will be no callbacks while the actors are sleeping. + +@see PxScene.setContactModifyCallback() PxScene.getContactModifyCallback() +*/ +class PxCCDContactModifyCallback +{ +public: + + /** + \brief Passes modifiable arrays of contacts to the application. + + The initial contacts are as determined fresh each frame by collision detection. + + The number of contacts can not be changed, so you cannot add your own contacts. You may however + disable contacts using PxContactSet::ignore(). + + @see PxContactModifyPair + */ + virtual void onCCDContactModify(PxContactModifyPair* const pairs, PxU32 count) = 0; + +protected: + virtual ~PxCCDContactModifyCallback(){} +}; + + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/PxDeletionListener.h b/sources/PhysX/PhysX/include/PxDeletionListener.h new file mode 100644 index 00000000..953bd7bd --- /dev/null +++ b/sources/PhysX/PhysX/include/PxDeletionListener.h @@ -0,0 +1,106 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX_DELETIONLISTENER +#define PX_PHYSICS_NX_DELETIONLISTENER +/** \addtogroup physics +@{ +*/ + +#include "PxPhysXConfig.h" +#include "common/PxBase.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + + +/** +\brief Flags specifying deletion event types. + +@see PxDeletionListener::onRelease PxPhysics.registerDeletionListener() +*/ +struct PxDeletionEventFlag +{ + enum Enum + { + eUSER_RELEASE = (1<<0), //!< The user has called release on an object. + eMEMORY_RELEASE = (1<<1) //!< The destructor of an object has been called and the memory has been released. + }; +}; + +/** +\brief Collection of set bits defined in PxDeletionEventFlag. + +@see PxDeletionEventFlag +*/ +typedef PxFlags PxDeletionEventFlags; +PX_FLAGS_OPERATORS(PxDeletionEventFlag::Enum,PxU8) + + +/** +\brief interface to get notification on object deletion + +*/ +class PxDeletionListener +{ +public: + /** + \brief Notification if an object or its memory gets released + + If release() gets called on a PxBase object, an eUSER_RELEASE event will get fired immediately. The object state can be queried in the callback but + it is not allowed to change the state. Furthermore, when reading from the object it is the user's responsibility to make sure that no other thread + is writing at the same time to the object (this includes the simulation itself, i.e., #PxScene::fetchResults() must not get called at the same time). + + Calling release() on a PxBase object does not necessarily trigger its destructor immediately. For example, the object can be shared and might still + be referenced by other objects or the simulation might still be running and accessing the object state. In such cases the destructor will be called + as soon as it is safe to do so. After the destruction of the object and its memory, an eMEMORY_RELEASE event will get fired. In this case it is not + allowed to dereference the object pointer in the callback. + + \param[in] observed The object for which the deletion event gets fired. + \param[in] userData The user data pointer of the object for which the deletion event gets fired. Not available for all object types in which case it will be set to 0. + \param[in] deletionEvent The type of deletion event. Do not dereference the object pointer argument if the event is eMEMORY_RELEASE. + + */ + virtual void onRelease(const PxBase* observed, void* userData, PxDeletionEventFlag::Enum deletionEvent) = 0; + +protected: + PxDeletionListener() {} + virtual ~PxDeletionListener() {} +}; + + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/PxFiltering.h b/sources/PhysX/PhysX/include/PxFiltering.h new file mode 100644 index 00000000..91105ca9 --- /dev/null +++ b/sources/PhysX/PhysX/include/PxFiltering.h @@ -0,0 +1,738 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX_FILTERING +#define PX_PHYSICS_NX_FILTERING +/** \addtogroup physics +@{ +*/ + +#include "PxPhysXConfig.h" +#include "foundation/PxFlags.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxActor; +class PxShape; + +static const PxU32 INVALID_FILTER_PAIR_INDEX = 0xffffffff; + +/** +\brief Collection of flags describing the actions to take for a collision pair. + +@see PxPairFlags PxSimulationFilterShader.filter() PxSimulationFilterCallback +*/ +struct PxPairFlag +{ + enum Enum + { + /** + \brief Process the contacts of this collision pair in the dynamics solver. + + \note Only takes effect if the colliding actors are rigid bodies. + */ + eSOLVE_CONTACT = (1<<0), + + /** + \brief Call contact modification callback for this collision pair + + \note Only takes effect if the colliding actors are rigid bodies. + + @see PxContactModifyCallback + */ + eMODIFY_CONTACTS = (1<<1), + + /** + \brief Call contact report callback or trigger callback when this collision pair starts to be in contact. + + If one of the two collision objects is a trigger shape (see #PxShapeFlag::eTRIGGER_SHAPE) + then the trigger callback will get called as soon as the other object enters the trigger volume. + If none of the two collision objects is a trigger shape then the contact report callback will get + called when the actors of this collision pair start to be in contact. + + \note Only takes effect if the colliding actors are rigid bodies. + + \note Only takes effect if eDETECT_DISCRETE_CONTACT or eDETECT_CCD_CONTACT is raised + + @see PxSimulationEventCallback.onContact() PxSimulationEventCallback.onTrigger() + */ + eNOTIFY_TOUCH_FOUND = (1<<2), + + /** + \brief Call contact report callback while this collision pair is in contact + + If none of the two collision objects is a trigger shape then the contact report callback will get + called while the actors of this collision pair are in contact. + + \note Triggers do not support this event. Persistent trigger contacts need to be tracked separately by observing eNOTIFY_TOUCH_FOUND/eNOTIFY_TOUCH_LOST events. + + \note Only takes effect if the colliding actors are rigid bodies. + + \note No report will get sent if the objects in contact are sleeping. + + \note Only takes effect if eDETECT_DISCRETE_CONTACT or eDETECT_CCD_CONTACT is raised + + \note If this flag gets enabled while a pair is in touch already, there will be no eNOTIFY_TOUCH_PERSISTS events until the pair loses and regains touch. + + @see PxSimulationEventCallback.onContact() PxSimulationEventCallback.onTrigger() + */ + eNOTIFY_TOUCH_PERSISTS = (1<<3), + + /** + \brief Call contact report callback or trigger callback when this collision pair stops to be in contact + + If one of the two collision objects is a trigger shape (see #PxShapeFlag::eTRIGGER_SHAPE) + then the trigger callback will get called as soon as the other object leaves the trigger volume. + If none of the two collision objects is a trigger shape then the contact report callback will get + called when the actors of this collision pair stop to be in contact. + + \note Only takes effect if the colliding actors are rigid bodies. + + \note This event will also get triggered if one of the colliding objects gets deleted. + + \note Only takes effect if eDETECT_DISCRETE_CONTACT or eDETECT_CCD_CONTACT is raised + + @see PxSimulationEventCallback.onContact() PxSimulationEventCallback.onTrigger() + */ + eNOTIFY_TOUCH_LOST = (1<<4), + + /** + \brief Call contact report callback when this collision pair is in contact during CCD passes. + + If CCD with multiple passes is enabled, then a fast moving object might bounce on and off the same + object multiple times. Hence, the same pair might be in contact multiple times during a simulation step. + This flag will make sure that all the detected collision during CCD will get reported. For performance + reasons, the system can not always tell whether the contact pair lost touch in one of the previous CCD + passes and thus can also not always tell whether the contact is new or has persisted. eNOTIFY_TOUCH_CCD + just reports when the two collision objects were detected as being in contact during a CCD pass. + + \note Only takes effect if the colliding actors are rigid bodies. + + \note Trigger shapes are not supported. + + \note Only takes effect if eDETECT_CCD_CONTACT is raised + + @see PxSimulationEventCallback.onContact() PxSimulationEventCallback.onTrigger() + */ + eNOTIFY_TOUCH_CCD = (1<<5), + + /** + \brief Call contact report callback when the contact force between the actors of this collision pair exceeds one of the actor-defined force thresholds. + + \note Only takes effect if the colliding actors are rigid bodies. + + \note Only takes effect if eDETECT_DISCRETE_CONTACT or eDETECT_CCD_CONTACT is raised + + @see PxSimulationEventCallback.onContact() + */ + eNOTIFY_THRESHOLD_FORCE_FOUND = (1<<6), + + /** + \brief Call contact report callback when the contact force between the actors of this collision pair continues to exceed one of the actor-defined force thresholds. + + \note Only takes effect if the colliding actors are rigid bodies. + + \note If a pair gets re-filtered and this flag has previously been disabled, then the report will not get fired in the same frame even if the force threshold has been reached in the + previous one (unless #eNOTIFY_THRESHOLD_FORCE_FOUND has been set in the previous frame). + + \note Only takes effect if eDETECT_DISCRETE_CONTACT or eDETECT_CCD_CONTACT is raised + + @see PxSimulationEventCallback.onContact() + */ + eNOTIFY_THRESHOLD_FORCE_PERSISTS = (1<<7), + + /** + \brief Call contact report callback when the contact force between the actors of this collision pair falls below one of the actor-defined force thresholds (includes the case where this collision pair stops being in contact). + + \note Only takes effect if the colliding actors are rigid bodies. + + \note If a pair gets re-filtered and this flag has previously been disabled, then the report will not get fired in the same frame even if the force threshold has been reached in the + previous one (unless #eNOTIFY_THRESHOLD_FORCE_FOUND or #eNOTIFY_THRESHOLD_FORCE_PERSISTS has been set in the previous frame). + + \note Only takes effect if eDETECT_DISCRETE_CONTACT or eDETECT_CCD_CONTACT is raised + + @see PxSimulationEventCallback.onContact() + */ + eNOTIFY_THRESHOLD_FORCE_LOST = (1<<8), + + /** + \brief Provide contact points in contact reports for this collision pair. + + \note Only takes effect if the colliding actors are rigid bodies and if used in combination with the flags eNOTIFY_TOUCH_... or eNOTIFY_THRESHOLD_FORCE_... + + \note Only takes effect if eDETECT_DISCRETE_CONTACT or eDETECT_CCD_CONTACT is raised + + @see PxSimulationEventCallback.onContact() PxContactPair PxContactPair.extractContacts() + */ + eNOTIFY_CONTACT_POINTS = (1<<9), + + /** + \brief This flag is used to indicate whether this pair generates discrete collision detection contacts. + + \note Contacts are only responded to if eSOLVE_CONTACT is enabled. + */ + eDETECT_DISCRETE_CONTACT = (1<<10), + + /** + \brief This flag is used to indicate whether this pair generates CCD contacts. + + \note The contacts will only be responded to if eSOLVE_CONTACT is enabled on this pair. + \note The scene must have PxSceneFlag::eENABLE_CCD enabled to use this feature. + \note Non-static bodies of the pair should have PxRigidBodyFlag::eENABLE_CCD specified for this feature to work correctly. + \note This flag is not supported with trigger shapes. However, CCD trigger events can be emulated using non-trigger shapes + and requesting eNOTIFY_TOUCH_FOUND and eNOTIFY_TOUCH_LOST and not raising eSOLVE_CONTACT on the pair. + + @see PxRigidBodyFlag::eENABLE_CCD + @see PxSceneFlag::eENABLE_CCD + */ + eDETECT_CCD_CONTACT = (1<<11), + + /** + \brief Provide pre solver velocities in contact reports for this collision pair. + + If the collision pair has contact reports enabled, the velocities of the rigid bodies before contacts have been solved + will be provided in the contact report callback unless the pair lost touch in which case no data will be provided. + + \note Usually it is not necessary to request these velocities as they will be available by querying the velocity from the provided + PxRigidActor object directly. However, it might be the case that the velocity of a rigid body gets set while the simulation is running + in which case the PxRigidActor would return this new velocity in the contact report callback and not the velocity the simulation used. + + @see PxSimulationEventCallback.onContact(), PxContactPairVelocity, PxContactPairHeader.extraDataStream + */ + ePRE_SOLVER_VELOCITY = (1<<12), + + /** + \brief Provide post solver velocities in contact reports for this collision pair. + + If the collision pair has contact reports enabled, the velocities of the rigid bodies after contacts have been solved + will be provided in the contact report callback unless the pair lost touch in which case no data will be provided. + + @see PxSimulationEventCallback.onContact(), PxContactPairVelocity, PxContactPairHeader.extraDataStream + */ + ePOST_SOLVER_VELOCITY = (1<<13), + + /** + \brief Provide rigid body poses in contact reports for this collision pair. + + If the collision pair has contact reports enabled, the rigid body poses at the contact event will be provided + in the contact report callback unless the pair lost touch in which case no data will be provided. + + \note Usually it is not necessary to request these poses as they will be available by querying the pose from the provided + PxRigidActor object directly. However, it might be the case that the pose of a rigid body gets set while the simulation is running + in which case the PxRigidActor would return this new pose in the contact report callback and not the pose the simulation used. + Another use case is related to CCD with multiple passes enabled, A fast moving object might bounce on and off the same + object multiple times. This flag can be used to request the rigid body poses at the time of impact for each such collision event. + + @see PxSimulationEventCallback.onContact(), PxContactPairPose, PxContactPairHeader.extraDataStream + */ + eCONTACT_EVENT_POSE = (1<<14), + + eNEXT_FREE = (1<<15), //!< For internal use only. + + /** + \brief Provided default flag to do simple contact processing for this collision pair. + */ + eCONTACT_DEFAULT = eSOLVE_CONTACT | eDETECT_DISCRETE_CONTACT, + + /** + \brief Provided default flag to get commonly used trigger behavior for this collision pair. + */ + eTRIGGER_DEFAULT = eNOTIFY_TOUCH_FOUND | eNOTIFY_TOUCH_LOST | eDETECT_DISCRETE_CONTACT + }; +}; + +/** +\brief Bitfield that contains a set of raised flags defined in PxPairFlag. + +@see PxPairFlag +*/ +typedef PxFlags PxPairFlags; +PX_FLAGS_OPERATORS(PxPairFlag::Enum, PxU16) + + + +/** +\brief Collection of flags describing the filter actions to take for a collision pair. + +@see PxFilterFlags PxSimulationFilterShader PxSimulationFilterCallback +*/ +struct PxFilterFlag +{ + enum Enum + { + /** + \brief Ignore the collision pair as long as the bounding volumes of the pair objects overlap. + + Killed pairs will be ignored by the simulation and won't run through the filter again until one + of the following occurs: + + \li The bounding volumes of the two objects overlap again (after being separated) + \li The user enforces a re-filtering (see #PxScene::resetFiltering()) + + @see PxScene::resetFiltering() + */ + eKILL = (1<<0), + + /** + \brief Ignore the collision pair as long as the bounding volumes of the pair objects overlap or until filtering relevant data changes for one of the collision objects. + + Suppressed pairs will be ignored by the simulation and won't make another filter request until one + of the following occurs: + + \li Same conditions as for killed pairs (see #eKILL) + \li The filter data or the filter object attributes change for one of the collision objects + + @see PxFilterData PxFilterObjectAttributes + */ + eSUPPRESS = (1<<1), + + /** + \brief Invoke the filter callback (#PxSimulationFilterCallback::pairFound()) for this collision pair. + + @see PxSimulationFilterCallback + */ + eCALLBACK = (1<<2), + + /** + \brief Track this collision pair with the filter callback mechanism. + + When the bounding volumes of the collision pair lose contact, the filter callback #PxSimulationFilterCallback::pairLost() + will be invoked. Furthermore, the filter status of the collision pair can be adjusted through #PxSimulationFilterCallback::statusChange() + once per frame (until a pairLost() notification occurs). + + @see PxSimulationFilterCallback + */ + eNOTIFY = (1<<3) | eCALLBACK, + + /** + \brief Provided default to get standard behavior: + + The application configure the pair's collision properties once when bounding volume overlap is found and + doesn't get asked again about that pair until overlap status or filter properties changes, or re-filtering is requested. + + No notification is provided when bounding volume overlap is lost + + The pair will not be killed or suppressed, so collision detection will be processed + */ + + eDEFAULT = 0 + }; +}; + +/** +\brief Bitfield that contains a set of raised flags defined in PxFilterFlag. + +@see PxFilterFlag +*/ +typedef PxFlags PxFilterFlags; +PX_FLAGS_OPERATORS(PxFilterFlag::Enum, PxU16) + + +/** +\brief PxFilterData is user-definable data which gets passed into the collision filtering shader and/or callback. + +@see PxShape.setSimulationFilterData() PxShape.getSimulationFilterData() PxSimulationFilterShader PxSimulationFilterCallback +*/ +struct PxFilterData +{ +//= ATTENTION! ===================================================================================== +// Changing the data layout of this class breaks the binary serialization format. See comments for +// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData +// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION +// accordingly. +//================================================================================================== + + PX_INLINE PxFilterData(const PxEMPTY) + { + } + + /** + \brief Default constructor. + */ + PX_INLINE PxFilterData() + { + word0 = word1 = word2 = word3 = 0; + } + + /** + \brief Copy constructor. + */ + PX_INLINE PxFilterData(const PxFilterData& fd) : word0(fd.word0), word1(fd.word1), word2(fd.word2), word3(fd.word3) {} + + /** + \brief Constructor to set filter data initially. + */ + PX_INLINE PxFilterData(PxU32 w0, PxU32 w1, PxU32 w2, PxU32 w3) : word0(w0), word1(w1), word2(w2), word3(w3) {} + + /** + \brief (re)sets the structure to the default. + */ + PX_INLINE void setToDefault() + { + *this = PxFilterData(); + } + + /** + \brief Assignment operator + */ + PX_INLINE void operator = (const PxFilterData& fd) + { + word0 = fd.word0; + word1 = fd.word1; + word2 = fd.word2; + word3 = fd.word3; + } + + /** + \brief Comparison operator to allow use in Array. + */ + PX_INLINE bool operator == (const PxFilterData& a) const + { + return a.word0 == word0 && a.word1 == word1 && a.word2 == word2 && a.word3 == word3; + } + + /** + \brief Comparison operator to allow use in Array. + */ + PX_INLINE bool operator != (const PxFilterData& a) const + { + return !(a == *this); + } + + PxU32 word0; + PxU32 word1; + PxU32 word2; + PxU32 word3; +}; + + +/** +\brief Identifies each type of filter object. + +@see PxGetFilterObjectType() +*/ +struct PxFilterObjectType +{ + enum Enum + { + /** + \brief A static rigid body + @see PxRigidStatic + */ + eRIGID_STATIC, + + /** + \brief A dynamic rigid body + @see PxRigidDynamic + */ + eRIGID_DYNAMIC, + + /** + \brief An articulation + @see PxArticulation + */ + eARTICULATION, + + //brief internal use only! + eMAX_TYPE_COUNT = 16, + + //brief internal use only! + eUNDEFINED = eMAX_TYPE_COUNT-1 + }; +}; + + +// For internal use only +struct PxFilterObjectFlag +{ + enum Enum + { + eKINEMATIC = (1<<4), + eTRIGGER = (1<<5) + }; +}; + + +/** +\brief Structure which gets passed into the collision filtering shader and/or callback providing additional information on objects of a collision pair + +@see PxSimulationFilterShader PxSimulationFilterCallback getActorType() PxFilterObjectIsKinematic() PxFilterObjectIsTrigger() +*/ +typedef PxU32 PxFilterObjectAttributes; + + +/** +\brief Extract filter object type from the filter attributes of a collision pair object + +\param[in] attr The filter attribute of a collision pair object +\return The type of the collision pair object. + +@see PxFilterObjectType +*/ +PX_INLINE PxFilterObjectType::Enum PxGetFilterObjectType(PxFilterObjectAttributes attr) +{ + return PxFilterObjectType::Enum(attr & (PxFilterObjectType::eMAX_TYPE_COUNT-1)); +} + + +/** +\brief Specifies whether the collision object belongs to a kinematic rigid body + +\param[in] attr The filter attribute of a collision pair object +\return True if the object belongs to a kinematic rigid body, else false + +@see PxRigidBodyFlag::eKINEMATIC +*/ +PX_INLINE bool PxFilterObjectIsKinematic(PxFilterObjectAttributes attr) +{ + return (attr & PxFilterObjectFlag::eKINEMATIC) != 0; +} + + +/** +\brief Specifies whether the collision object is a trigger shape + +\param[in] attr The filter attribute of a collision pair object +\return True if the object is a trigger shape, else false + +@see PxShapeFlag::eTRIGGER_SHAPE +*/ +PX_INLINE bool PxFilterObjectIsTrigger(PxFilterObjectAttributes attr) +{ + return (attr & PxFilterObjectFlag::eTRIGGER) != 0; +} + + +/** +\brief Filter shader to specify handling of collision pairs. + +Collision filtering is a mechanism to specify how a pair of potentially colliding objects should be processed by the +simulation. A pair of objects is potentially colliding if the bounding volumes of the two objects overlap. +In short, a collision filter decides whether a collision pair should get processed, temporarily ignored or discarded. +If a collision pair should get processed, the filter can additionally specify how it should get processed, for instance, +whether contacts should get resolved, which callbacks should get invoked or which reports should be sent etc. + +\note A default implementation of a filter shader is provided in the PhysX extensions library, see #PxDefaultSimulationFilterShader. + +@see PxSceneDesc.filterShader PxSimulationFilterCallback +*/ + +/** +\brief Filter method to specify how a pair of potentially colliding objects should be processed. + +Return the PxFilterFlag flags and set the PxPairFlag flags to define what the simulation should do with the given collision pair. + +This methods gets called when: +\li The bounding volumes of two objects start to overlap. +\li The bounding volumes of two objects overlap and the filter data or filter attributes of one of the objects changed +\li A re-filtering was forced through resetFiltering() (see #PxScene::resetFiltering()) +\li Filtering is requested in scene queries + +\note Certain pairs of objects are always ignored and this method does not get called. This is the case for the +following pairs: + +\li Pair of static rigid actors +\li A static rigid actor and a kinematic actor (unless one is a trigger or if explicitly enabled through PxPairFilteringMode::eKEEP) +\li Two kinematic actors (unless one is a trigger or if explicitly enabled through PxPairFilteringMode::eKEEP) +\li Two jointed rigid bodies and the joint was defined to disable collision +\li Two articulation links if connected through an articulation joint + +\note This is a performance critical method and should be stateless. You should neither access external objects +from within this method nor should you call external methods that are not inlined. If you need a more complex +logic to filter a collision pair then use the filter callback mechanism for this pair (see #PxSimulationFilterCallback, +#PxFilterFlag::eCALLBACK, #PxFilterFlag::eNOTIFY). + +\param[in] attributes0 The filter attribute of the first object +\param[in] filterData0 The custom filter data of the first object +\param[in] attributes1 The filter attribute of the second object +\param[in] filterData1 The custom filter data of the second object +\param[out] pairFlags Flags giving additional information on how an accepted pair should get processed +\param[in] constantBlock The constant global filter data (see #PxSceneDesc.filterShaderData) +\param[in] constantBlockSize Size of the global filter data (see #PxSceneDesc.filterShaderDataSize) +\return Filter flags defining whether the pair should be discarded, temporarily ignored, processed and whether the +filter callback should get invoked for this pair. + +@see PxSimulationFilterCallback PxFilterData PxFilterObjectAttributes PxFilterFlag PxFilterFlags PxPairFlag PxPairFlags +*/ + +typedef PxFilterFlags (*PxSimulationFilterShader) + (PxFilterObjectAttributes attributes0, PxFilterData filterData0, + PxFilterObjectAttributes attributes1, PxFilterData filterData1, + PxPairFlags& pairFlags, const void* constantBlock, PxU32 constantBlockSize); + + + +/** +\brief Filter callback to specify handling of collision pairs. + +This class is provided to implement more complex and flexible collision pair filtering logic, for instance, taking +the state of the user application into account. Filter callbacks also give the user the opportunity to track collision +pairs and update their filter state. + +You might want to check the documentation on #PxSimulationFilterShader as well since it includes more general information +on filtering. + +\note SDK state should not be modified from within the callbacks. In particular objects should not +be created or destroyed. If state modification is needed then the changes should be stored to a buffer +and performed after the simulation step. + +\note The callbacks may execute in user threads or simulation threads, possibly simultaneously. The corresponding objects +may have been deleted by the application earlier in the frame. It is the application's responsibility to prevent race conditions +arising from using the SDK API in the callback while an application thread is making write calls to the scene, and to ensure that +the callbacks are thread-safe. Return values which depend on when the callback is called during the frame will introduce nondeterminism +into the simulation. + +@see PxSceneDesc.filterCallback PxSimulationFilterShader +*/ +class PxSimulationFilterCallback +{ +public: + + /** + \brief Filter method to specify how a pair of potentially colliding objects should be processed. + + This method gets called when the filter flags returned by the filter shader (see #PxSimulationFilterShader) + indicate that the filter callback should be invoked (#PxFilterFlag::eCALLBACK or #PxFilterFlag::eNOTIFY set). + Return the PxFilterFlag flags and set the PxPairFlag flags to define what the simulation should do with the given + collision pair. + + \param[in] pairID Unique ID of the collision pair used to issue filter status changes for the pair (see #statusChange()) + \param[in] attributes0 The filter attribute of the first object + \param[in] filterData0 The custom filter data of the first object + \param[in] a0 Actor pointer of the first object + \param[in] s0 Shape pointer of the first object (NULL if the object has no shapes) + \param[in] attributes1 The filter attribute of the second object + \param[in] filterData1 The custom filter data of the second object + \param[in] a1 Actor pointer of the second object + \param[in] s1 Shape pointer of the second object (NULL if the object has no shapes) + \param[in,out] pairFlags In: Pair flags returned by the filter shader. Out: Additional information on how an accepted pair should get processed + \return Filter flags defining whether the pair should be discarded, temporarily ignored or processed and whether the pair + should be tracked and send a report on pair deletion through the filter callback + + @see PxSimulationFilterShader PxFilterData PxFilterObjectAttributes PxFilterFlag PxPairFlag + */ + virtual PxFilterFlags pairFound( PxU32 pairID, + PxFilterObjectAttributes attributes0, PxFilterData filterData0, const PxActor* a0, const PxShape* s0, + PxFilterObjectAttributes attributes1, PxFilterData filterData1, const PxActor* a1, const PxShape* s1, + PxPairFlags& pairFlags) = 0; + + /** + \brief Callback to inform that a tracked collision pair is gone. + + This method gets called when a collision pair disappears or gets re-filtered. Only applies to + collision pairs which have been marked as filter callback pairs (#PxFilterFlag::eNOTIFY set in #pairFound()). + + \param[in] pairID Unique ID of the collision pair that disappeared + \param[in] attributes0 The filter attribute of the first object + \param[in] filterData0 The custom filter data of the first object + \param[in] attributes1 The filter attribute of the second object + \param[in] filterData1 The custom filter data of the second object + \param[in] objectRemoved True if the pair was lost because one of the objects got removed from the scene + + @see pairFound() PxSimulationFilterShader PxFilterData PxFilterObjectAttributes + */ + virtual void pairLost( PxU32 pairID, + PxFilterObjectAttributes attributes0, + PxFilterData filterData0, + PxFilterObjectAttributes attributes1, + PxFilterData filterData1, + bool objectRemoved) = 0; + + /** + \brief Callback to give the opportunity to change the filter state of a tracked collision pair. + + This method gets called once per simulation step to let the application change the filter and pair + flags of a collision pair that has been reported in #pairFound() and requested callbacks by + setting #PxFilterFlag::eNOTIFY. To request a change of filter status, the target pair has to be + specified by its ID, the new filter and pair flags have to be provided and the method should return true. + + \note If this method changes the filter status of a collision pair and the pair should keep being tracked + by the filter callbacks then #PxFilterFlag::eNOTIFY has to be set. + + \note The application is responsible to ensure that this method does not get called for pairs that have been + reported as lost, see #pairLost(). + + \param[out] pairID ID of the collision pair for which the filter status should be changed + \param[out] pairFlags The new pairFlags to apply to the collision pair + \param[out] filterFlags The new filterFlags to apply to the collision pair + \return True if the changes should be applied. In this case the method will get called again. False if + no more status changes should be done in the current simulation step. In that case the provided flags will be discarded. + + @see pairFound() pairLost() PxFilterFlag PxPairFlag + */ + virtual bool statusChange(PxU32& pairID, PxPairFlags& pairFlags, PxFilterFlags& filterFlags) = 0; + +protected: + virtual ~PxSimulationFilterCallback() {} +}; + +struct PxPairFilteringMode +{ + enum Enum + { + /** + Output pair from BP, potentially send to user callbacks, create regular interaction object. + + Enable contact pair filtering between kinematic/static or kinematic/kinematic rigid bodies. + + By default contacts between these are suppressed (see #PxFilterFlag::eSUPPRESS) and don't get reported to the filter mechanism. + Use this mode if these pairs should go through the filtering pipeline nonetheless. + + \note This mode is not mutable, and must be set in PxSceneDesc at scene creation. + */ + eKEEP, + + /** + Output pair from BP, create interaction marker. Can be later switched to regular interaction. + */ + eSUPPRESS, + + /** + Don't output pair from BP. Cannot be later switched to regular interaction, needs "resetFiltering" call. + */ + eKILL, + + /** + Default is eSUPPRESS for compatibility with previous PhysX versions. + */ + eDEFAULT = eSUPPRESS + }; +}; + + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/PxForceMode.h b/sources/PhysX/PhysX/include/PxForceMode.h new file mode 100644 index 00000000..9d425d54 --- /dev/null +++ b/sources/PhysX/PhysX/include/PxForceMode.h @@ -0,0 +1,66 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX_FORCE_MODE +#define PX_PHYSICS_NX_FORCE_MODE + +#include "foundation/PxPreprocessor.h" + +/** \addtogroup physics +@{ +*/ + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief Parameter to addForce() and addTorque() calls, determines the exact operation that is carried out. + +@see PxRigidBody.addForce() PxRigidBody.addTorque() +*/ +struct PxForceMode +{ + enum Enum + { + eFORCE, //!< parameter has unit of mass * distance/ time^2, i.e. a force + eIMPULSE, //!< parameter has unit of mass * distance /time + eVELOCITY_CHANGE, //!< parameter has unit of distance / time, i.e. the effect is mass independent: a velocity change. + eACCELERATION //!< parameter has unit of distance/ time^2, i.e. an acceleration. It gets treated just like a force except the mass is not divided out before integration. + }; +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/PxFoundation.h b/sources/PhysX/PhysX/include/PxFoundation.h new file mode 100644 index 00000000..4a4a14df --- /dev/null +++ b/sources/PhysX/PhysX/include/PxFoundation.h @@ -0,0 +1,159 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_FOUNDATION_PX_FOUNDATION_H +#define PX_FOUNDATION_PX_FOUNDATION_H + +/** \addtogroup foundation + @{ +*/ + +#include "foundation/Px.h" +#include "foundation/PxErrors.h" +#include "foundation/PxFoundationConfig.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief Foundation SDK singleton class. + +You need to have an instance of this class to instance the higher level SDKs. +*/ +class PX_FOUNDATION_API PxFoundation +{ + public: + /** + \brief Destroys the instance it is called on. + + The operation will fail, if there are still modules referencing the foundation object. Release all dependent modules + prior + to calling this method. + + @see PxCreateFoundation() + */ + virtual void release() = 0; + + /** + retrieves error callback + */ + virtual PxErrorCallback& getErrorCallback() = 0; + + /** + Sets mask of errors to report. + */ + virtual void setErrorLevel(PxErrorCode::Enum mask = PxErrorCode::eMASK_ALL) = 0; + + /** + Retrieves mask of errors to be reported. + */ + virtual PxErrorCode::Enum getErrorLevel() const = 0; + + /** + Retrieves the allocator this object was created with. + */ + virtual PxAllocatorCallback& getAllocatorCallback() = 0; + + /** + Retrieves if allocation names are being passed to allocator callback. + */ + virtual bool getReportAllocationNames() const = 0; + + /** + Set if allocation names are being passed to allocator callback. + \details Enabled by default in debug and checked build, disabled by default in profile and release build. + */ + virtual void setReportAllocationNames(bool value) = 0; + + protected: + virtual ~PxFoundation() + { + } +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** +\brief Creates an instance of the foundation class + +The foundation class is needed to initialize higher level SDKs. There may be only one instance per process. +Calling this method after an instance has been created already will result in an error message and NULL will be +returned. + +\param version Version number we are expecting (should be #PX_PHYSICS_VERSION) +\param allocator User supplied interface for allocating memory(see #PxAllocatorCallback) +\param errorCallback User supplied interface for reporting errors and displaying messages(see #PxErrorCallback) +\return Foundation instance on success, NULL if operation failed + +@see PxFoundation +*/ + +PX_C_EXPORT PX_FOUNDATION_API physx::PxFoundation* PX_CALL_CONV +PxCreateFoundation(physx::PxU32 version, physx::PxAllocatorCallback& allocator, physx::PxErrorCallback& errorCallback); +/** +\brief Retrieves the Foundation SDK after it has been created. + +\note The behavior of this method is undefined if the foundation instance has not been created already. + +@see PxCreateFoundation() +*/ +#if PX_CLANG +#if PX_LINUX +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreturn-type-c-linkage" +#endif // PX_LINUX +#endif // PX_CLANG +PX_C_EXPORT PX_FOUNDATION_API physx::PxFoundation& PX_CALL_CONV PxGetFoundation(); +#if PX_CLANG +#if PX_LINUX +#pragma clang diagnostic pop +#endif // PX_LINUX +#endif // PX_CLANG + +namespace physx +{ +class PxProfilerCallback; +} + +/** +\brief Get the callback that will be used for all profiling. +*/ +PX_C_EXPORT PX_FOUNDATION_API physx::PxProfilerCallback* PX_CALL_CONV PxGetProfilerCallback(); + +/** +\brief Set the callback that will be used for all profiling. +*/ +PX_C_EXPORT PX_FOUNDATION_API void PX_CALL_CONV PxSetProfilerCallback(physx::PxProfilerCallback* profiler); + +/** @} */ +#endif // PX_FOUNDATION_PX_FOUNDATION_H diff --git a/sources/PhysX/PhysX/include/PxImmediateMode.h b/sources/PhysX/PhysX/include/PxImmediateMode.h new file mode 100644 index 00000000..f5887230 --- /dev/null +++ b/sources/PhysX/PhysX/include/PxImmediateMode.h @@ -0,0 +1,673 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_PHYSICS_IMMEDIATE_MODE +#define PX_PHYSICS_IMMEDIATE_MODE +/** \addtogroup immediatemode +@{ */ + +#include "PxPhysXConfig.h" +#include "solver/PxSolverDefs.h" +#include "collision/PxCollisionDefs.h" +#include "PxArticulationReducedCoordinate.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +#if !PX_DOXYGEN +namespace immediate +{ +#endif + + /** + \brief Structure to store rigid body properties + */ + struct PxRigidBodyData + { + PX_ALIGN(16, PxVec3 linearVelocity); //!< 12 Linear velocity + PxReal invMass; //!< 16 Inverse mass + PxVec3 angularVelocity; //!< 28 Angular velocity + PxReal maxDepenetrationVelocity; //!< 32 Maximum de-penetration velocity + PxVec3 invInertia; //!< 44 Mass-space inverse interia diagonal vector + PxReal maxContactImpulse; //!< 48 Maximum permissable contact impulse + PxTransform body2World; //!< 76 World space transform + PxReal linearDamping; //!< 80 Linear damping coefficient + PxReal angularDamping; //!< 84 Angular damping coefficient + PxReal maxLinearVelocitySq; //!< 88 Squared maximum linear velocity + PxReal maxAngularVelocitySq; //!< 92 Squared maximum angular velocity + PxU32 pad; //!< 96 Padding for 16-byte alignment + }; + + /** + \brief Callback class to record contact points produced by immediate::PxGenerateContacts + */ + class PxContactRecorder + { + public: + /** + \brief Method to record new contacts + \param [in] contactPoints The contact points produced + \param [in] nbContacts The number of contact points produced + \param [in] index The index of this pair. This is an index from 0-N-1 identifying which pair this relates to from within the array of pairs passed to PxGenerateContacts + \return a boolean to indicate if this callback successfully stored the contacts or not. + */ + virtual bool recordContacts(const Gu::ContactPoint* contactPoints, const PxU32 nbContacts, const PxU32 index) = 0; + + virtual ~PxContactRecorder(){} + }; + + /** + \brief Constructs a PxSolverBodyData structure based on rigid body properties. Applies gravity, damping and clamps maximum velocity. + \param [in] inRigidData The array rigid body properties + \param [out] outSolverBodyData The array of solverBodyData produced to repreent these bodies + \param [in] nbBodies The total number of solver bodies to create + \param [in] gravity The gravity vector + \param [in] dt The timestep + */ + PX_C_EXPORT PX_PHYSX_CORE_API void PxConstructSolverBodies(const PxRigidBodyData* inRigidData, PxSolverBodyData* outSolverBodyData, const PxU32 nbBodies, const PxVec3& gravity, const PxReal dt); + + /** + \brief Constructs a PxSolverBodyData structure for a static body at a given pose. + \param [in] globalPose The pose of this static actor + \param [out] solverBodyData The solver body representation of this static actor + */ + PX_C_EXPORT PX_PHYSX_CORE_API void PxConstructStaticSolverBody(const PxTransform& globalPose, PxSolverBodyData& solverBodyData); + + /** + \brief Groups together sets of independent PxSolverConstraintDesc objects to be solved using SIMD SOA approach. + \param [in] solverConstraintDescs The set of solver constraint descs to batch + \param [in] nbConstraints The number of constraints to batch + \param [in,out] solverBodies The array of solver bodies that the constraints reference. Some fields in these structures are written to as scratch memory for the batching. + \param [in] nbBodies The number of bodies + \param [out] outBatchHeaders The batch headers produced by this batching process. This array must have at least 1 entry per input constraint + \param [out] outOrderedConstraintDescs A reordered copy of the constraint descs. This array is referenced by the constraint batches. This array must have at least 1 entry per input constraint. + \param [in,out] articulations The array of articulations that the constraints reference. Some fields in these structures are written to as scratch memory for the batching. + \param [in] nbArticulations The number of articulations + \return The total number of batches produced. This should be less than or equal to nbConstraints. + + \note This method considers all bodies within the range [0, nbBodies-1] to be valid dynamic bodies. A given dynamic body can only be referenced in a batch once. Static or kinematic bodies can be + referenced multiple times within a batch safely because constraints do not affect their velocities. The batching will implicitly consider any bodies outside of the range [0, nbBodies-1] to be + infinite mass (static or kinematic). This means that either appending static/kinematic to the end of the array of bodies or placing static/kinematic bodies at before the start body pointer + will ensure that the minimum number of batches are produced. + */ + PX_C_EXPORT PX_PHYSX_CORE_API PxU32 PxBatchConstraints( const PxSolverConstraintDesc* solverConstraintDescs, const PxU32 nbConstraints, PxSolverBody* solverBodies, const PxU32 nbBodies, + PxConstraintBatchHeader* outBatchHeaders, PxSolverConstraintDesc* outOrderedConstraintDescs, + Dy::ArticulationV** articulations=NULL, const PxU32 nbArticulations=0); + + /** + \brief Creates a set of contact constraint blocks. Note that, depending the results of PxBatchConstraints, each batchHeader may refer to up to 4 solverConstraintDescs. + This function will allocate both constraint and friction patch data via the PxConstraintAllocator provided. Constraint data is only valid until PxSolveConstraints has completed. + Friction data is to be retained and provided by the application for friction correlation. + + \param [in] batchHeaders Array of batch headers to process + \param [in] nbHeaders The total number of headers + \param [in] contactDescs An array of contact descs defining the pair and contact properties of each respective contacting pair + \param [in] allocator An allocator callback to allocate constraint and friction memory + \param [in] invDt The inverse timestep + \param [in] bounceThreshold The bounce threshold. Relative velocities below this will be solved by bias only. Relative velocities above this will be solved by restitution. If restitution is zero + then these pairs will always be solved by bias. + \param [in] frictionOffsetThreshold The friction offset threshold. Contacts whose separations are below this threshold can generate friction constraints. + \param [in] correlationDistance The correlation distance used by friction correlation to identify whether a friction patch is broken on the grounds of relation separation. + + \return a boolean to define if this method was successful or not. + */ + PX_C_EXPORT PX_PHYSX_CORE_API bool PxCreateContactConstraints(PxConstraintBatchHeader* batchHeaders, const PxU32 nbHeaders, PxSolverContactDesc* contactDescs, + PxConstraintAllocator& allocator, const PxReal invDt, const PxReal bounceThreshold, const PxReal frictionOffsetThreshold, const PxReal correlationDistance); + + /** + \brief Creates a set of joint constraint blocks. Note that, depending the results of PxBatchConstraints, the batchHeader may refer to up to 4 solverConstraintDescs + \param [in] batchHeaders The array of batch headers to be processed + \param [in] nbHeaders The total number of batch headers to process + \param [in] jointDescs An array of constraint prep descs defining the properties of the constraints being created + \param [in] allocator An allocator callback to allocate constraint data + \param [in] dt The timestep + \param [in] invDt The inverse timestep + \return a boolean indicating if this method was successful or not. + */ + PX_C_EXPORT PX_PHYSX_CORE_API bool PxCreateJointConstraints(PxConstraintBatchHeader* batchHeaders, const PxU32 nbHeaders, PxSolverConstraintPrepDesc* jointDescs, PxConstraintAllocator& allocator, const PxReal dt, const PxReal invDt); + + /** + \brief Creates a set of joint constraint blocks. This function runs joint shaders defined inside PxConstraint** param, fills in joint row information in jointDescs and then calls PxCreateJointConstraints. + \param [in] batchHeaders The set of batchHeaders to be processed + \param [in] nbBatchHeaders The number of batch headers to process. + \param [in] constraints The set of constraints to be used to produce constraint rows + \param [in,out] jointDescs An array of constraint prep descs defining the properties of the constraints being created + \param [in] allocator An allocator callback to allocate constraint data + \param [in] dt The timestep + \param [in] invDt The inverse timestep + \return a boolean indicating if this method was successful or not. + @see PxCreateJointConstraints + */ + PX_C_EXPORT PX_PHYSX_CORE_API bool PxCreateJointConstraintsWithShaders(PxConstraintBatchHeader* batchHeaders, const PxU32 nbBatchHeaders, PxConstraint** constraints, PxSolverConstraintPrepDesc* jointDescs, PxConstraintAllocator& allocator, const PxReal dt, const PxReal invDt); + + struct PxImmediateConstraint + { + PxConstraintSolverPrep prep; + const void* constantBlock; + }; + /** + \brief Creates a set of joint constraint blocks. This function runs joint shaders defined inside PxImmediateConstraint* param, fills in joint row information in jointDescs and then calls PxCreateJointConstraints. + \param [in] batchHeaders The set of batchHeaders to be processed + \param [in] nbBatchHeaders The number of batch headers to process. + \param [in] constraints The set of constraints to be used to produce constraint rows + \param [in,out] jointDescs An array of constraint prep descs defining the properties of the constraints being created + \param [in] allocator An allocator callback to allocate constraint data + \param [in] dt The timestep + \param [in] invDt The inverse timestep + \return a boolean indicating if this method was successful or not. + @see PxCreateJointConstraints + */ + PX_C_EXPORT PX_PHYSX_CORE_API bool PxCreateJointConstraintsWithImmediateShaders(PxConstraintBatchHeader* batchHeaders, const PxU32 nbBatchHeaders, PxImmediateConstraint* constraints, PxSolverConstraintPrepDesc* jointDescs, PxConstraintAllocator& allocator, const PxReal dt, const PxReal invDt); + + /** + \brief Iteratively solves the set of constraints defined by the provided PxConstraintBatchHeader and PxSolverConstraintDesc structures. Updates deltaVelocities inside the PxSolverBody structures. Produces resulting linear and angular motion velocities. + \param [in] batchHeaders The set of batch headers to be solved + \param [in] nbBatchHeaders The total number of batch headers to be solved + \param [in] solverConstraintDescs The reordererd set of solver constraint descs referenced by the batch headers + \param [in,out] solverBodies The set of solver bodies the bodies reference + \param [out] linearMotionVelocity The resulting linear motion velocity + \param [out] angularMotionVelocity The resulting angular motion velocity. + \param [in] nbSolverBodies The total number of solver bodies + \param [in] nbPositionIterations The number of position iterations to run + \param [in] nbVelocityIterations The number of velocity iterations to run + \param [in] dt Timestep. Only needed if articulations are sent to the function. + \param [in] invDt Inverse timestep. Only needed if articulations are sent to the function. + \param [in] nbSolverArticulations Number of articulations to solve constraints for. + \param [in] solverArticulations Array of articulations to solve constraints for. + */ + PX_C_EXPORT PX_PHYSX_CORE_API void PxSolveConstraints(const PxConstraintBatchHeader* batchHeaders, const PxU32 nbBatchHeaders, const PxSolverConstraintDesc* solverConstraintDescs, + const PxSolverBody* solverBodies, PxVec3* linearMotionVelocity, PxVec3* angularMotionVelocity, const PxU32 nbSolverBodies, const PxU32 nbPositionIterations, const PxU32 nbVelocityIterations, + const float dt=0.0f, const float invDt=0.0f, const PxU32 nbSolverArticulations=0, Dy::ArticulationV** solverArticulations=NULL); + + /** + \brief Integrates a rigid body, returning the new velocities and transforms. After this function has been called, solverBodyData stores all the body's velocity data. + + \param [in,out] solverBodyData The array of solver body data to be integrated + \param [in] solverBody The bodies' linear and angular velocities + \param [in] linearMotionVelocity The bodies' linear motion velocity array + \param [in] angularMotionState The bodies' angular motion velocity array + \param [in] nbBodiesToIntegrate The total number of bodies to integrate + \param [in] dt The timestep + */ + PX_C_EXPORT PX_PHYSX_CORE_API void PxIntegrateSolverBodies(PxSolverBodyData* solverBodyData, PxSolverBody* solverBody, const PxVec3* linearMotionVelocity, const PxVec3* angularMotionState, const PxU32 nbBodiesToIntegrate, const PxReal dt); + + /** + \brief Performs contact generation for a given pair of geometries at the specified poses. Produced contacts are stored in the provided Gu::ContactBuffer. Information is cached in PxCache structure + to accelerate future contact generation between pairs. This cache data is valid only as long as the memory provided by PxCacheAllocator has not been released/re-used. Recommendation is to + retain that data for a single simulation frame, discarding cached data after 2 frames. If the cached memory has been released/re-used prior to the corresponding pair having contact generation + performed again, it is the application's responsibility to reset the PxCache. + + \param [in] geom0 Array of geometries to perform collision detection on. + \param [in] geom1 Array of geometries to perform collision detection on + \param [in] pose0 Array of poses associated with the corresponding entry in the geom0 array + \param [in] pose1 Array of poses associated with the corresponding entry in the geom1 array + \param [in,out] contactCache Array of contact caches associated with each pair geom0[i] + geom1[i] + \param [in] nbPairs The total number of pairs to process + \param [in] contactRecorder A callback that is called to record contacts for each pair that detects contacts + \param [in] contactDistance The distance at which contacts begin to be generated between the pairs + \param [in] meshContactMargin The mesh contact margin. + \param [in] toleranceLength The toleranceLength. Used for scaling distance-based thresholds internally to produce appropriate results given simulations in different units + \param [in] allocator A callback to allocate memory for the contact cache + + \return a boolean indicating if the function was successful or not. + */ + PX_C_EXPORT PX_PHYSX_CORE_API bool PxGenerateContacts(const PxGeometry* const * geom0, const PxGeometry* const * geom1, const PxTransform* pose0, const PxTransform* pose1, PxCache* contactCache, const PxU32 nbPairs, PxContactRecorder& contactRecorder, + const PxReal contactDistance, const PxReal meshContactMargin, const PxReal toleranceLength, PxCacheAllocator& allocator); + + /** + \brief Register articulation-related solver functions. This is equivalent to PxRegisterArticulationsReducedCoordinate() for PxScene-level articulations. + Call this first to enable reduced coordinates articulations in immediate mode. + + @see PxRegisterArticulationsReducedCoordinate + */ + PX_C_EXPORT PX_PHYSX_CORE_API void PxRegisterImmediateArticulations(); + + struct PxArticulationJointData + { + PxTransform parentPose; + PxTransform childPose; + }; + + struct PxFeatherstoneArticulationJointData : PxArticulationJointData + { + PxArticulationJointType::Enum type; + PxArticulationMotion::Enum motion[PxArticulationAxis::eCOUNT]; + PxArticulationLimit limits[PxArticulationAxis::eCOUNT]; + PxArticulationDrive drives[PxArticulationAxis::eCOUNT]; + PxReal targetPos[PxArticulationAxis::eCOUNT]; + PxReal targetVel[PxArticulationAxis::eCOUNT]; + PxReal frictionCoefficient; + PxReal maxJointVelocity; + }; + + struct PxFeatherstoneArticulationData + { + PxArticulationFlags flags; + }; + + struct PxMutableLinkData + { + PxVec3 inverseInertia; + float inverseMass; + float linearDamping; + float angularDamping; + float maxLinearVelocitySq; + float maxAngularVelocitySq; + bool disableGravity; + }; + + struct PxLinkData + { + PxTransform pose; + PxVec3 linearVelocity; + PxVec3 angularVelocity; + }; + + struct PxFeatherstoneArticulationLinkData : PxMutableLinkData + { + PxFeatherstoneArticulationLinkData() { initData(); } + + void initData() + { + inboundJoint.type = PxArticulationJointType::eUNDEFINED; // For root + inboundJoint.parentPose = PxTransform(PxIdentity); + inboundJoint.childPose = PxTransform(PxIdentity); + inboundJoint.frictionCoefficient = 0.05f; + inboundJoint.maxJointVelocity = 100.0f; + + pose = PxTransform(PxIdentity); + parent = 0; + inverseInertia = PxVec3(1.0f); + inverseMass = 1.0f; + linearDamping = 0.05f; + angularDamping = 0.05f; + maxLinearVelocitySq = 100.0f * 100.0f; + maxAngularVelocitySq = 50.0f * 50.0f; + disableGravity = false; + + for(PxU32 i=0;i PxDataAccessFlags; +PX_FLAGS_OPERATORS(PxDataAccessFlag::Enum,PxU8) + + +/** +\brief Parent class for bulk data that is shared between the SDK and the application. +*/ +class PxLockedData +{ +public: + + /** + \brief Any combination of PxDataAccessFlag::eREADABLE and PxDataAccessFlag::eWRITABLE + @see PxDataAccessFlag + */ + virtual PxDataAccessFlags getDataAccessFlags() = 0; + + /** + \brief Unlocks the bulk data. + */ + virtual void unlock() = 0; + + /** + \brief virtual destructor + */ + virtual ~PxLockedData() {} +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/PxMaterial.h b/sources/PhysX/PhysX/include/PxMaterial.h new file mode 100644 index 00000000..d6f8685d --- /dev/null +++ b/sources/PhysX/PhysX/include/PxMaterial.h @@ -0,0 +1,337 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NXMATERIAL +#define PX_PHYSICS_NXMATERIAL +/** \addtogroup physics +@{ +*/ + +#include "PxPhysXConfig.h" +#include "common/PxBase.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxScene; + +/** +\brief Flags which control the behavior of a material. + +@see PxMaterial +*/ +struct PxMaterialFlag +{ + enum Enum + { + + /** + If this flag is set, friction computations are always skipped between shapes with this material and any other shape. + */ + eDISABLE_FRICTION = 1 << 0, + + /** + The difference between "normal" and "strong" friction is that the strong friction feature + remembers the "friction error" between simulation steps. The friction is a force trying to + hold objects in place (or slow them down) and this is handled in the solver. But since the + solver is only an approximation, the result of the friction calculation can include a small + "error" - e.g. a box resting on a slope should not move at all if the static friction is in + action, but could slowly glide down the slope because of a small friction error in each + simulation step. The strong friction counter-acts this by remembering the small error and + taking it to account during the next simulation step. + + However, in some cases the strong friction could cause problems, and this is why it is + possible to disable the strong friction feature by setting this flag. One example is + raycast vehicles, that are sliding fast across the surface, but still need a precise + steering behavior. It may be a good idea to reenable the strong friction when objects + are coming to a rest, to prevent them from slowly creeping down inclines. + + Note: This flag only has an effect if the PxMaterialFlag::eDISABLE_FRICTION bit is 0. + */ + eDISABLE_STRONG_FRICTION = 1 << 1, + + /** + This flag only has an effect if PxFrictionType::ePATCH friction model is used. + + When using the patch friction model, up to 2 friction anchors are generated per patch. As the number of friction anchors + can be smaller than the number of contacts, the normal force is accumulated over all contacts and used to compute friction + for all anchors. Where there are more than 2 anchors, this can produce frictional behavior that is too strong (approximately 2x as strong + as analytical models suggest). + + This flag causes the normal force to be distributed between the friction anchors such that the total amount of friction applied does not + exceed the analyical results. + */ + eIMPROVED_PATCH_FRICTION = 1 << 2 + }; +}; + +/** +\brief collection of set bits defined in PxMaterialFlag. + +@see PxMaterialFlag +*/ +typedef PxFlags PxMaterialFlags; +PX_FLAGS_OPERATORS(PxMaterialFlag::Enum,PxU16) + + +/** +\brief enumeration that determines the way in which two material properties will be combined to yield a friction or restitution coefficient for a collision. + +When two actors come in contact with each other, they each have materials with various coefficients, but we only need a single set of coefficients for the pair. + +Physics doesn't have any inherent combinations because the coefficients are determined empirically on a case by case +basis. However, simulating this with a pairwise lookup table is often impractical. + +For this reason the following combine behaviors are available: + +eAVERAGE +eMIN +eMULTIPLY +eMAX + +The effective combine mode for the pair is maximum(material0.combineMode, material1.combineMode). + +@see PxMaterial.setFrictionCombineMode() PxMaterial.getFrictionCombineMode() PxMaterial.setRestitutionCombineMode() PxMaterial.getFrictionCombineMode() +*/ +struct PxCombineMode +{ + enum Enum + { + eAVERAGE = 0, //!< Average: (a + b)/2 + eMIN = 1, //!< Minimum: minimum(a,b) + eMULTIPLY = 2, //!< Multiply: a*b + eMAX = 3, //!< Maximum: maximum(a,b) + eN_VALUES = 4, //!< This is not a valid combine mode, it is a sentinel to denote the number of possible values. We assert that the variable's value is smaller than this. + ePAD_32 = 0x7fffffff //!< This is not a valid combine mode, it is to assure that the size of the enum type is big enough. + }; +}; + +/** +\brief Material class to represent a set of surface properties. + +@see PxPhysics.createMaterial +*/ +class PxMaterial : public PxBase +{ +public: + + /** + \brief Decrements the reference count of a material and releases it if the new reference count is zero. + + @see PxPhysics.createMaterial() + */ + virtual void release() = 0; + + /** + \brief Returns the reference count of the material. + + At creation, the reference count of the material is 1. Every shape referencing this material increments the + count by 1. When the reference count reaches 0, and only then, the material gets destroyed automatically. + + \return the current reference count. + */ + virtual PxU32 getReferenceCount() const = 0; + + /** + \brief Acquires a counted reference to a material. + + This method increases the reference count of the material by 1. Decrement the reference count by calling release() + */ + virtual void acquireReference() = 0; + + /** + \brief Sets the coefficient of dynamic friction. + + The coefficient of dynamic friction should be in [0, PX_MAX_F32). If set to greater than staticFriction, the effective value of staticFriction will be increased to match. + + Sleeping: Does NOT wake any actors which may be affected. + + \param[in] coef Coefficient of dynamic friction. Range: [0, PX_MAX_F32) + + @see getDynamicFriction() + */ + virtual void setDynamicFriction(PxReal coef) = 0; + + /** + \brief Retrieves the DynamicFriction value. + + \return The coefficient of dynamic friction. + + @see setDynamicFriction + */ + virtual PxReal getDynamicFriction() const = 0; + + /** + \brief Sets the coefficient of static friction + + The coefficient of static friction should be in the range [0, PX_MAX_F32) + + Sleeping: Does NOT wake any actors which may be affected. + + \param[in] coef Coefficient of static friction. Range: [0, PX_MAX_F32) + + @see getStaticFriction() + */ + virtual void setStaticFriction(PxReal coef) = 0; + + /** + \brief Retrieves the coefficient of static friction. + \return The coefficient of static friction. + + @see setStaticFriction + */ + virtual PxReal getStaticFriction() const = 0; + + /** + \brief Sets the coefficient of restitution + + A coefficient of 0 makes the object bounce as little as possible, higher values up to 1.0 result in more bounce. + + Sleeping: Does NOT wake any actors which may be affected. + + \param[in] rest Coefficient of restitution. Range: [0,1] + + @see getRestitution() + */ + virtual void setRestitution(PxReal rest) = 0; + + /** + \brief Retrieves the coefficient of restitution. + + See #setRestitution. + + \return The coefficient of restitution. + + @see setRestitution() + */ + virtual PxReal getRestitution() const = 0; + + /** + \brief Raises or clears a particular material flag. + + See the list of flags #PxMaterialFlag + + Sleeping: Does NOT wake any actors which may be affected. + + \param[in] flag The PxMaterial flag to raise(set) or clear. + + @see getFlags() PxMaterialFlag + */ + virtual void setFlag(PxMaterialFlag::Enum flag, bool) = 0; + + + /** + \brief sets all the material flags. + + See the list of flags #PxMaterialFlag + + Sleeping: Does NOT wake any actors which may be affected. + + */ + virtual void setFlags( PxMaterialFlags inFlags ) = 0; + + /** + \brief Retrieves the flags. See #PxMaterialFlag. + + \return The material flags. + + @see PxMaterialFlag setFlags() + */ + virtual PxMaterialFlags getFlags() const = 0; + + /** + \brief Sets the friction combine mode. + + See the enum ::PxCombineMode . + + Sleeping: Does NOT wake any actors which may be affected. + + \param[in] combMode Friction combine mode to set for this material. See #PxCombineMode. + + @see PxCombineMode getFrictionCombineMode setStaticFriction() setDynamicFriction() + */ + virtual void setFrictionCombineMode(PxCombineMode::Enum combMode) = 0; + + /** + \brief Retrieves the friction combine mode. + + See #setFrictionCombineMode. + + \return The friction combine mode for this material. + + @see PxCombineMode setFrictionCombineMode() + */ + virtual PxCombineMode::Enum getFrictionCombineMode() const = 0; + + /** + \brief Sets the restitution combine mode. + + See the enum ::PxCombineMode . + + Sleeping: Does NOT wake any actors which may be affected. + + \param[in] combMode Restitution combine mode for this material. See #PxCombineMode. + + @see PxCombineMode getRestitutionCombineMode() setRestitution() + */ + virtual void setRestitutionCombineMode(PxCombineMode::Enum combMode) = 0; + + /** + \brief Retrieves the restitution combine mode. + + See #setRestitutionCombineMode. + + \return The coefficient of restitution combine mode for this material. + + @see PxCombineMode setRestitutionCombineMode getRestitution() + */ + virtual PxCombineMode::Enum getRestitutionCombineMode() const = 0; + + //public variables: + void* userData; //!< user can assign this to whatever, usually to create a 1:1 relationship with a user object. + + virtual const char* getConcreteTypeName() const { return "PxMaterial"; } + +protected: + PX_INLINE PxMaterial(PxType concreteType, PxBaseFlags baseFlags) : PxBase(concreteType, baseFlags), userData(NULL) {} + PX_INLINE PxMaterial(PxBaseFlags baseFlags) : PxBase(baseFlags) {} + virtual ~PxMaterial() {} + virtual bool isKindOf(const char* name) const { return !::strcmp("PxMaterial", name) || PxBase::isKindOf(name); } + +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/PxPhysXConfig.h b/sources/PhysX/PhysX/include/PxPhysXConfig.h new file mode 100644 index 00000000..ea329bb2 --- /dev/null +++ b/sources/PhysX/PhysX/include/PxPhysXConfig.h @@ -0,0 +1,78 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX +#define PX_PHYSICS_NX + +/** Configuration include file for PhysX SDK */ + +/** \addtogroup physics +@{ +*/ + +#include "common/PxPhysXCommonConfig.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxPhysics; +class PxShape; + +class PxActor; +class PxRigidActor; +class PxRigidStatic; +class PxRigidDynamic; +class PxConstraint; +class PxConstraintDesc; + +class PxArticulation; +class PxArticulationReducedCoordinate; +class PxArticulationBase; +class PxArticulationLink; +class PxArticulationJoint; +class PxArticulationJointReducedCoordinate; +class PxArticulationJointBase; + +class PxMaterial; + +class PxScene; +class PxSceneDesc; +class PxTolerancesScale; + +class PxAggregate; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/PxPhysics.h b/sources/PhysX/PhysX/include/PxPhysics.h new file mode 100644 index 00000000..f8efe3f9 --- /dev/null +++ b/sources/PhysX/PhysX/include/PxPhysics.h @@ -0,0 +1,729 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_PHYSICS_NX_PHYSICS +#define PX_PHYSICS_NX_PHYSICS + +/** \addtogroup physics +@{ +*/ + +#include "PxPhysXConfig.h" +#include "PxDeletionListener.h" +#include "foundation/PxTransform.h" +#include "PxShape.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxPvd; +class PxPhysicsInsertionCallback; + +class PxRigidActor; +class PxConstraintConnector; +struct PxConstraintShaderTable; + +class PxGeometry; +class PxFoundation; +class PxSerializationRegistry; + +class PxPruningStructure; +class PxBVHStructure; + +/** +\brief Abstract singleton factory class used for instancing objects in the Physics SDK. + +In addition you can use PxPhysics to set global parameters which will effect all scenes and create +objects that can be shared across multiple scenes. + +You can get an instance of this class by calling PxCreateBasePhysics() or PxCreatePhysics() with pre-registered modules. + +@see PxCreatePhysics() PxCreateBasePhysics() PxScene PxVisualizationParameter +*/ +class PxPhysics +{ +public: + + /** @name Basics + */ + //@{ + + virtual ~PxPhysics() {} + + /** + \brief Destroys the instance it is called on. + + Use this release method to destroy an instance of this class. Be sure + to not keep a reference to this object after calling release. + Avoid release calls while a scene is simulating (in between simulate() and fetchResults() calls). + + Note that this must be called once for each prior call to PxCreatePhysics, as + there is a reference counter. Also note that you mustn't destroy the allocator or the error callback (if available) until after the + reference count reaches 0 and the SDK is actually removed. + + Releasing an SDK will also release any scenes, triangle meshes, convex meshes, heightfields and shapes + created through it, provided the user hasn't already done so. + + \note This function is required to be called to release foundation usage. + + @see PxCreatePhysics() + */ + virtual void release() = 0; + + /** + \brief Retrieves the Foundation instance. + \return A reference to the Foundation object. + */ + virtual PxFoundation& getFoundation() = 0; + + /** + \brief Creates an aggregate with the specified maximum size and selfCollision property. + + \param [in] maxSize The maximum number of actors that may be placed in the aggregate. + \param [in] enableSelfCollision Whether the aggregate supports self-collision + \return The new aggregate. + + @see PxAggregate + */ + virtual PxAggregate* createAggregate(PxU32 maxSize, bool enableSelfCollision) = 0; + + /** + \brief Returns the simulation tolerance parameters. + \return The current simulation tolerance parameters. + */ + virtual const PxTolerancesScale& getTolerancesScale() const = 0; + + //@} + /** @name Meshes + */ + //@{ + + /** + \brief Creates a triangle mesh object. + + This can then be instanced into #PxShape objects. + + \param [in] stream The triangle mesh stream. + \return The new triangle mesh. + + @see PxTriangleMesh PxMeshPreprocessingFlag PxTriangleMesh.release() PxInputStream PxTriangleMeshFlag + */ + virtual PxTriangleMesh* createTriangleMesh(PxInputStream& stream) = 0; + + /** + \brief Return the number of triangle meshes that currently exist. + + \return Number of triangle meshes. + + @see getTriangleMeshes() + */ + virtual PxU32 getNbTriangleMeshes() const = 0; + + /** + \brief Writes the array of triangle mesh pointers to a user buffer. + + Returns the number of pointers written. + + The ordering of the triangle meshes in the array is not specified. + + \param [out] userBuffer The buffer to receive triangle mesh pointers. + \param [in] bufferSize The number of triangle mesh pointers which can be stored in the buffer. + \param [in] startIndex Index of first mesh pointer to be retrieved + \return The number of triangle mesh pointers written to userBuffer, this should be less or equal to bufferSize. + + @see getNbTriangleMeshes() PxTriangleMesh + */ + virtual PxU32 getTriangleMeshes(PxTriangleMesh** userBuffer, PxU32 bufferSize, PxU32 startIndex=0) const = 0; + + /** + \brief Creates a heightfield object from previously cooked stream. + + This can then be instanced into #PxShape objects. + + \param [in] stream The heightfield mesh stream. + \return The new heightfield. + + @see PxHeightField PxHeightField.release() PxInputStream PxRegisterHeightFields + */ + virtual PxHeightField* createHeightField(PxInputStream& stream) = 0; + + /** + \brief Return the number of heightfields that currently exist. + + \return Number of heightfields. + + @see getHeightFields() + */ + virtual PxU32 getNbHeightFields() const = 0; + + /** + \brief Writes the array of heightfield pointers to a user buffer. + + Returns the number of pointers written. + + The ordering of the heightfields in the array is not specified. + + \param [out] userBuffer The buffer to receive heightfield pointers. + \param [in] bufferSize The number of heightfield pointers which can be stored in the buffer. + \param [in] startIndex Index of first heightfield pointer to be retrieved + \return The number of heightfield pointers written to userBuffer, this should be less or equal to bufferSize. + + @see getNbHeightFields() PxHeightField + */ + virtual PxU32 getHeightFields(PxHeightField** userBuffer, PxU32 bufferSize, PxU32 startIndex=0) const = 0; + + /** + \brief Creates a convex mesh object. + + This can then be instanced into #PxShape objects. + + \param [in] stream The stream to load the convex mesh from. + \return The new convex mesh. + + @see PxConvexMesh PxConvexMesh.release() PxInputStream createTriangleMesh() PxConvexMeshGeometry PxShape + */ + virtual PxConvexMesh* createConvexMesh(PxInputStream &stream) = 0; + + /** + \brief Return the number of convex meshes that currently exist. + + \return Number of convex meshes. + + @see getConvexMeshes() + */ + virtual PxU32 getNbConvexMeshes() const = 0; + + /** + \brief Writes the array of convex mesh pointers to a user buffer. + + Returns the number of pointers written. + + The ordering of the convex meshes in the array is not specified. + + \param [out] userBuffer The buffer to receive convex mesh pointers. + \param [in] bufferSize The number of convex mesh pointers which can be stored in the buffer. + \param [in] startIndex Index of first convex mesh pointer to be retrieved + \return The number of convex mesh pointers written to userBuffer, this should be less or equal to bufferSize. + + @see getNbConvexMeshes() PxConvexMesh + */ + virtual PxU32 getConvexMeshes(PxConvexMesh** userBuffer, PxU32 bufferSize, PxU32 startIndex=0) const = 0; + + /** + \brief Creates a bounding volume hierarchy structure. + + \param [in] stream The stream to load the BVH structure from. + \return The new BVH structure. + + @see PxBVHStructure PxInputStream + */ + virtual PxBVHStructure* createBVHStructure(PxInputStream &stream) = 0; + + /** + \brief Return the number of bounding volume hierarchy structures that currently exist. + + \return Number of bounding volume hierarchy structures. + + @see getBVHStructures() + */ + virtual PxU32 getNbBVHStructures() const = 0; + + /** + \brief Writes the array of bounding volume hierarchy structure pointers to a user buffer. + + Returns the number of pointers written. + + The ordering of the BVH structures in the array is not specified. + + \param [out] userBuffer The buffer to receive BVH structure pointers. + \param [in] bufferSize The number of BVH structure pointers which can be stored in the buffer. + \param [in] startIndex Index of first BVH structure pointer to be retrieved + \return The number of BVH structure pointers written to userBuffer, this should be less or equal to bufferSize. + + @see getNbBVHStructures() PxBVHStructure + */ + virtual PxU32 getBVHStructures(PxBVHStructure** userBuffer, PxU32 bufferSize, PxU32 startIndex=0) const = 0; + + //@} + /** @name Scenes + */ + //@{ + + /** + \brief Creates a scene. + + \note Every scene uses a Thread Local Storage slot. This imposes a platform specific limit on the + number of scenes that can be created. + + \param [in] sceneDesc Scene descriptor. See #PxSceneDesc + \return The new scene object. + + @see PxScene PxScene.release() PxSceneDesc + */ + virtual PxScene* createScene(const PxSceneDesc& sceneDesc) = 0; + + /** + \brief Gets number of created scenes. + + \return The number of scenes created. + + @see getScene() + */ + virtual PxU32 getNbScenes() const = 0; + + /** + \brief Writes the array of scene pointers to a user buffer. + + Returns the number of pointers written. + + The ordering of the scene pointers in the array is not specified. + + \param [out] userBuffer The buffer to receive scene pointers. + \param [in] bufferSize The number of scene pointers which can be stored in the buffer. + \param [in] startIndex Index of first scene pointer to be retrieved + \return The number of scene pointers written to userBuffer, this should be less or equal to bufferSize. + + @see getNbScenes() PxScene + */ + virtual PxU32 getScenes(PxScene** userBuffer, PxU32 bufferSize, PxU32 startIndex=0) const = 0; + + //@} + /** @name Actors + */ + //@{ + + /** + \brief Creates a static rigid actor with the specified pose and all other fields initialized + to their default values. + + \param [in] pose The initial pose of the actor. Must be a valid transform + + @see PxRigidStatic + */ + virtual PxRigidStatic* createRigidStatic(const PxTransform& pose) = 0; + + /** + \brief Creates a dynamic rigid actor with the specified pose and all other fields initialized + to their default values. + + \param [in] pose The initial pose of the actor. Must be a valid transform + + @see PxRigidDynamic + */ + virtual PxRigidDynamic* createRigidDynamic(const PxTransform& pose) = 0; + + /** + \brief Creates a pruning structure from actors. + + \note Every provided actor needs at least one shape with the eSCENE_QUERY_SHAPE flag set. + \note Both static and dynamic actors can be provided. + \note It is not allowed to pass in actors which are already part of a scene. + \note Articulation links cannot be provided. + + \param [in] actors Array of actors to add to the pruning structure. Must be non NULL. + \param [in] nbActors Number of actors in the array. Must be >0. + \return Pruning structure created from given actors, or NULL if any of the actors did not comply with the above requirements. + @see PxActor PxPruningStructure + */ + virtual PxPruningStructure* createPruningStructure(PxRigidActor*const* actors, PxU32 nbActors) = 0; + + //@} + /** @name Shapes + */ + //@{ + + /** + \brief Creates a shape which may be attached to multiple actors + + The shape will be created with a reference count of 1. + + \param [in] geometry The geometry for the shape + \param [in] material The material for the shape + \param [in] isExclusive Whether this shape is exclusive to a single actor or maybe be shared + \param [in] shapeFlags The PxShapeFlags to be set + + Shared shapes are not mutable when they are attached to an actor + + @see PxShape + */ + PX_FORCE_INLINE PxShape* createShape( const PxGeometry& geometry, + const PxMaterial& material, + bool isExclusive = false, + PxShapeFlags shapeFlags = PxShapeFlag::eVISUALIZATION | PxShapeFlag::eSCENE_QUERY_SHAPE | PxShapeFlag::eSIMULATION_SHAPE) + { + PxMaterial* materialPtr = const_cast(&material); + return createShape(geometry, &materialPtr, 1, isExclusive, shapeFlags); + } + + /** + \brief Creates a shape which may be attached to multiple actors + + The shape will be created with a reference count of 1. + + \param [in] geometry The geometry for the shape + \param [in] materials The materials for the shape + \param [in] materialCount The number of materials + \param [in] isExclusive Whether this shape is exclusive to a single actor or may be shared + \param [in] shapeFlags The PxShapeFlags to be set + + Shared shapes are not mutable when they are attached to an actor + + @see PxShape + */ + virtual PxShape* createShape(const PxGeometry& geometry, + PxMaterial*const * materials, + PxU16 materialCount, + bool isExclusive = false, + PxShapeFlags shapeFlags = PxShapeFlag::eVISUALIZATION | PxShapeFlag::eSCENE_QUERY_SHAPE | PxShapeFlag::eSIMULATION_SHAPE) = 0; + + /** + \brief Return the number of shapes that currently exist. + + \return Number of shapes. + + @see getShapes() + */ + virtual PxU32 getNbShapes() const = 0; + + /** + \brief Writes the array of shape pointers to a user buffer. + + Returns the number of pointers written. + + The ordering of the shapes in the array is not specified. + + \param [out] userBuffer The buffer to receive shape pointers. + \param [in] bufferSize The number of shape pointers which can be stored in the buffer. + \param [in] startIndex Index of first shape pointer to be retrieved + \return The number of shape pointers written to userBuffer, this should be less or equal to bufferSize. + + @see getNbShapes() PxShape + */ + virtual PxU32 getShapes(PxShape** userBuffer, PxU32 bufferSize, PxU32 startIndex=0) const = 0; + + //@} + /** @name Constraints and Articulations + */ + //@{ + + /** + \brief Creates a constraint shader. + + \note A constraint shader will get added automatically to the scene the two linked actors belong to. Either, but not both, of actor0 and actor1 may + be NULL to denote attachment to the world. + + \param [in] actor0 The first actor + \param [in] actor1 The second actor + \param [in] connector The connector object, which the SDK uses to communicate with the infrastructure for the constraint + \param [in] shaders The shader functions for the constraint + \param [in] dataSize The size of the data block for the shader + + \return The new shader. + + @see PxConstraint + */ + virtual PxConstraint* createConstraint(PxRigidActor* actor0, PxRigidActor* actor1, PxConstraintConnector& connector, const PxConstraintShaderTable& shaders, PxU32 dataSize) = 0; + + /** + \brief Creates an articulation with all fields initialized to their default values. + + \return the new articulation + + @see PxArticulation, PxRegisterArticulations + */ + virtual PxArticulation* createArticulation() = 0; + + /** + \brief Creates a reduced coordinate articulation with all fields initialized to their default values. + + \return the new articulation + + @see PxArticulationReducedCoordinate, PxRegisterArticulationsReducedCoordinate + */ + virtual PxArticulationReducedCoordinate* createArticulationReducedCoordinate() = 0; + + + //@} + /** @name Materials + */ + //@{ + + /** + \brief Creates a new material with default properties. + + \return The new material. + + \param [in] staticFriction The coefficient of static friction + \param [in] dynamicFriction The coefficient of dynamic friction + \param [in] restitution The coefficient of restitution + + @see PxMaterial + */ + virtual PxMaterial* createMaterial(PxReal staticFriction, PxReal dynamicFriction, PxReal restitution) = 0; + + + /** + \brief Return the number of materials that currently exist. + + \return Number of materials. + + @see getMaterials() + */ + virtual PxU32 getNbMaterials() const = 0; + + /** + \brief Writes the array of material pointers to a user buffer. + + Returns the number of pointers written. + + The ordering of the materials in the array is not specified. + + \param [out] userBuffer The buffer to receive material pointers. + \param [in] bufferSize The number of material pointers which can be stored in the buffer. + \param [in] startIndex Index of first material pointer to be retrieved + \return The number of material pointers written to userBuffer, this should be less or equal to bufferSize. + + @see getNbMaterials() PxMaterial + */ + virtual PxU32 getMaterials(PxMaterial** userBuffer, PxU32 bufferSize, PxU32 startIndex=0) const = 0; + + //@} + /** @name Deletion Listeners + */ + //@{ + + /** + \brief Register a deletion listener. Listeners will be called whenever an object is deleted. + + It is illegal to register or unregister a deletion listener while deletions are being processed. + + \note By default a registered listener will receive events from all objects. Set the restrictedObjectSet parameter to true on registration and use #registerDeletionListenerObjects to restrict the received events to specific objects. + + \note The deletion events are only supported on core PhysX objects. In general, objects in extension modules do not provide this functionality, however, in the case of PxJoint objects, the underlying PxConstraint will send the events. + + \param [in] observer Observer object to send notifications to. + \param [in] deletionEvents The deletion event types to get notified of. + \param [in] restrictedObjectSet If false, the deletion listener will get events from all objects, else the objects to receive events from have to be specified explicitly through #registerDeletionListenerObjects. + + @see PxDeletionListener unregisterDeletionListener + */ + virtual void registerDeletionListener(PxDeletionListener& observer, const PxDeletionEventFlags& deletionEvents, bool restrictedObjectSet = false) = 0; + + /** + \brief Unregister a deletion listener. + + It is illegal to register or unregister a deletion listener while deletions are being processed. + + \param [in] observer Observer object to send notifications to + + @see PxDeletionListener registerDeletionListener + */ + virtual void unregisterDeletionListener(PxDeletionListener& observer) = 0; + + /** + \brief Register specific objects for deletion events. + + This method allows for a deletion listener to limit deletion events to specific objects only. + + \note It is illegal to register or unregister objects while deletions are being processed. + + \note The deletion listener has to be registered through #registerDeletionListener() and configured to support restricted objects sets prior to this method being used. + + \param [in] observer Observer object to send notifications to. + \param [in] observables List of objects for which to receive deletion events. Only PhysX core objects are supported. In the case of PxJoint objects, the underlying PxConstraint can be used to get the events. + \param [in] observableCount Size of the observables list. + + @see PxDeletionListener unregisterDeletionListenerObjects + */ + virtual void registerDeletionListenerObjects(PxDeletionListener& observer, const PxBase* const* observables, PxU32 observableCount) = 0; + + /** + \brief Unregister specific objects for deletion events. + + This method allows to clear previously registered objects for a deletion listener (see #registerDeletionListenerObjects()). + + \note It is illegal to register or unregister objects while deletions are being processed. + + \note The deletion listener has to be registered through #registerDeletionListener() and configured to support restricted objects sets prior to this method being used. + + \param [in] observer Observer object to stop sending notifications to. + \param [in] observables List of objects for which to not receive deletion events anymore. + \param [in] observableCount Size of the observables list. + + @see PxDeletionListener registerDeletionListenerObjects + */ + virtual void unregisterDeletionListenerObjects(PxDeletionListener& observer, const PxBase* const* observables, PxU32 observableCount) = 0; + + /** + \brief Gets PxPhysics object insertion interface. + + The insertion interface is needed ie. for PxCooking::createTriangleMesh, this allows runtime mesh creation. This is not advised to do, please + use offline cooking if possible. + + @see PxCooking::createTriangleMesh PxCooking::createHeightfield + */ + virtual PxPhysicsInsertionCallback& getPhysicsInsertionCallback() = 0; + + //@} +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** +\brief Enables the usage of the articulations feature. This function is called automatically inside PxCreatePhysics(). +On resource constrained platforms, it is possible to call PxCreateBasePhysics() and then NOT call this function +to save on code memory if your application does not use articulations. In this case the linker should strip out +the relevant implementation code from the library. If you need to use articulations but not some other optional +component, you shoud call PxCreateBasePhysics() followed by this call. +*/ +PX_C_EXPORT PX_PHYSX_CORE_API void PX_CALL_CONV PxRegisterArticulations(physx::PxPhysics& physics); + + +/** +\brief Enables the usage of the reduced coordinate articulations feature. This function is called automatically inside PxCreatePhysics(). +On resource constrained platforms, it is possible to call PxCreateBasePhysics() and then NOT call this function +to save on code memory if your application does not use articulations. In this case the linker should strip out +the relevant implementation code from the library. If you need to use articulations but not some other optional +component, you shoud call PxCreateBasePhysics() followed by this call. +*/ +PX_C_EXPORT PX_PHYSX_CORE_API void PX_CALL_CONV PxRegisterArticulationsReducedCoordinate(physx::PxPhysics& physics); + +/** +\brief Enables the usage of the heightfield feature. + +This call will link the default 'unified' implementation of heightfields which is identical to the narrow phase of triangle meshes. +This function is called automatically inside PxCreatePhysics(). + +On resource constrained platforms, it is possible to call PxCreateBasePhysics() and then NOT call this function +to save on code memory if your application does not use heightfields. In this case the linker should strip out +the relevant implementation code from the library. If you need to use heightfield but not some other optional +component, you shoud call PxCreateBasePhysics() followed by this call. + +You must call this function at a time where no ::PxScene instance exists, typically before calling PxPhysics::createScene(). +This is to prevent a change to the heightfield implementation code at runtime which would have undefined results. + +Calling PxCreateBasePhysics() and then attempting to create a heightfield shape without first calling +::PxRegisterHeightFields(), will result in an error. +*/ +PX_C_EXPORT PX_PHYSX_CORE_API void PX_CALL_CONV PxRegisterHeightFields(physx::PxPhysics& physics); + +/** +\brief Creates an instance of the physics SDK with minimal additional components registered + +Creates an instance of this class. May not be a class member to avoid name mangling. +Pass the constant #PX_PHYSICS_VERSION as the argument. +There may be only one instance of this class per process. Calling this method after an instance +has been created already will result in an error message and NULL will be returned. + +\param version Version number we are expecting(should be #PX_PHYSICS_VERSION) +\param foundation Foundation instance (see PxFoundation) +\param scale values used to determine default tolerances for objects at creation time +\param trackOutstandingAllocations true if you want to track memory allocations + so a debugger connection partway through your physics simulation will get + an accurate map of everything that has been allocated so far. This could have a memory + and performance impact on your simulation hence it defaults to off. +\param pvd When pvd points to a valid PxPvd instance (PhysX Visual Debugger), a connection to the specified PxPvd instance is created. + If pvd is NULL no connection will be attempted. +\return PxPhysics instance on success, NULL if operation failed + +@see PxPhysics, PxFoundation, PxTolerancesScale, PxPvd +*/ +PX_C_EXPORT PX_PHYSX_CORE_API physx::PxPhysics* PX_CALL_CONV PxCreateBasePhysics(physx::PxU32 version, + physx::PxFoundation& foundation, + const physx::PxTolerancesScale& scale, + bool trackOutstandingAllocations = false, + physx::PxPvd* pvd = NULL); + +/** +\brief Creates an instance of the physics SDK. + +Creates an instance of this class. May not be a class member to avoid name mangling. +Pass the constant #PX_PHYSICS_VERSION as the argument. +There may be only one instance of this class per process. Calling this method after an instance +has been created already will result in an error message and NULL will be returned. + +Calling this will register all optional code modules (Articulations and HeightFields), preparing them for use. +If you do not need some of these modules, consider calling PxCreateBasePhysics() instead and registering needed +modules manually. + +\param version Version number we are expecting(should be #PX_PHYSICS_VERSION) +\param foundation Foundation instance (see PxFoundation) +\param scale values used to determine default tolerances for objects at creation time +\param trackOutstandingAllocations true if you want to track memory allocations + so a debugger connection partway through your physics simulation will get + an accurate map of everything that has been allocated so far. This could have a memory + and performance impact on your simulation hence it defaults to off. +\param pvd When pvd points to a valid PxPvd instance (PhysX Visual Debugger), a connection to the specified PxPvd instance is created. + If pvd is NULL no connection will be attempted. +\return PxPhysics instance on success, NULL if operation failed + +@see PxPhysics, PxCreateBasePhysics, PxRegisterArticulations, PxRegisterArticulationsReducedCoordinate, PxRegisterHeightFields +*/ +PX_INLINE physx::PxPhysics* PxCreatePhysics(physx::PxU32 version, + physx::PxFoundation& foundation, + const physx::PxTolerancesScale& scale, + bool trackOutstandingAllocations = false, + physx::PxPvd* pvd = NULL ) +{ + physx::PxPhysics* physics = PxCreateBasePhysics(version, foundation, scale, trackOutstandingAllocations, pvd); + if(!physics) + return NULL; + + PxRegisterArticulations(*physics); + PxRegisterArticulationsReducedCoordinate(*physics); + PxRegisterHeightFields(*physics); + + return physics; +} + + +/** +\brief Retrieves the Physics SDK after it has been created. + +Before using this function the user must call #PxCreatePhysics(). + +\note The behavior of this method is undefined if the Physics SDK instance has not been created already. +*/ +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreturn-type-c-linkage" +#endif + +PX_C_EXPORT PX_PHYSX_CORE_API physx::PxPhysics& PX_CALL_CONV PxGetPhysics(); + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/PxPhysicsAPI.h b/sources/PhysX/PhysX/include/PxPhysicsAPI.h new file mode 100644 index 00000000..1fbfb0af --- /dev/null +++ b/sources/PhysX/PhysX/include/PxPhysicsAPI.h @@ -0,0 +1,217 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NXPHYSICS_API +#define PX_PHYSICS_NXPHYSICS_API +/** \addtogroup physics +@{ +*/ + +/** +This is the main include header for the Physics SDK, for users who +want to use a single #include file. + +Alternatively, one can instead directly #include a subset of the below files. +*/ + +// Foundation SDK +#include "foundation/Px.h" +#include "foundation/PxAllocatorCallback.h" +#include "foundation/PxAssert.h" +#include "foundation/PxBitAndData.h" +#include "foundation/PxBounds3.h" +#include "foundation/PxErrorCallback.h" +#include "foundation/PxErrors.h" +#include "foundation/PxFlags.h" +#include "foundation/PxIntrinsics.h" +#include "foundation/PxIO.h" +#include "foundation/PxMat33.h" +#include "foundation/PxMat44.h" +#include "foundation/PxMath.h" +#include "foundation/PxMathUtils.h" +#include "foundation/PxPlane.h" +#include "foundation/PxPreprocessor.h" +#include "foundation/PxQuat.h" +#include "foundation/PxSimpleTypes.h" +#include "foundation/PxStrideIterator.h" +#include "foundation/PxTransform.h" +#include "foundation/PxUnionCast.h" +#include "foundation/PxVec2.h" +#include "foundation/PxVec3.h" +#include "foundation/PxVec4.h" + +//Not physics specific utilities and common code +#include "common/PxCoreUtilityTypes.h" +#include "common/PxPhysXCommonConfig.h" +#include "common/PxRenderBuffer.h" +#include "common/PxBase.h" +#include "common/PxTolerancesScale.h" +#include "common/PxTypeInfo.h" +#include "common/PxStringTable.h" +#include "common/PxSerializer.h" +#include "common/PxMetaData.h" +#include "common/PxMetaDataFlags.h" +#include "common/PxSerialFramework.h" +#include "common/PxPhysicsInsertionCallback.h" + +//Task Manager +#include "task/PxTask.h" + +// Cuda Mananger +#if PX_SUPPORT_GPU_PHYSX +#include "gpu/PxGpu.h" +#endif + +//Geometry Library +#include "geometry/PxBoxGeometry.h" +#include "geometry/PxBVHStructure.h" +#include "geometry/PxCapsuleGeometry.h" +#include "geometry/PxConvexMesh.h" +#include "geometry/PxConvexMeshGeometry.h" +#include "geometry/PxGeometry.h" +#include "geometry/PxGeometryHelpers.h" +#include "geometry/PxGeometryQuery.h" +#include "geometry/PxHeightField.h" +#include "geometry/PxHeightFieldDesc.h" +#include "geometry/PxHeightFieldFlag.h" +#include "geometry/PxHeightFieldGeometry.h" +#include "geometry/PxHeightFieldSample.h" +#include "geometry/PxMeshQuery.h" +#include "geometry/PxMeshScale.h" +#include "geometry/PxPlaneGeometry.h" +#include "geometry/PxSimpleTriangleMesh.h" +#include "geometry/PxSphereGeometry.h" +#include "geometry/PxTriangle.h" +#include "geometry/PxTriangleMesh.h" +#include "geometry/PxTriangleMeshGeometry.h" + + +// PhysX Core SDK +#include "PxActor.h" +#include "PxAggregate.h" +#include "PxArticulation.h" +#include "PxArticulationReducedCoordinate.h" +#include "PxArticulationJoint.h" +#include "PxArticulationJointReducedCoordinate.h" +#include "PxArticulationLink.h" +#include "PxBatchQuery.h" +#include "PxBatchQueryDesc.h" +#include "PxClient.h" +#include "PxConstraint.h" +#include "PxConstraintDesc.h" +#include "PxContact.h" +#include "PxContactModifyCallback.h" +#include "PxDeletionListener.h" +#include "PxFiltering.h" +#include "PxForceMode.h" +#include "PxFoundation.h" +#include "PxLockedData.h" +#include "PxMaterial.h" +#include "PxPhysics.h" +#include "PxPhysicsVersion.h" +#include "PxPhysXConfig.h" +#include "PxQueryFiltering.h" +#include "PxQueryReport.h" +#include "PxRigidActor.h" +#include "PxRigidBody.h" +#include "PxRigidDynamic.h" +#include "PxRigidStatic.h" +#include "PxScene.h" +#include "PxSceneDesc.h" +#include "PxSceneLock.h" +#include "PxShape.h" +#include "PxSimulationEventCallback.h" +#include "PxSimulationStatistics.h" +#include "PxVisualizationParameter.h" +#include "PxPruningStructure.h" + +//Character Controller +#include "characterkinematic/PxBoxController.h" +#include "characterkinematic/PxCapsuleController.h" +#include "characterkinematic/PxController.h" +#include "characterkinematic/PxControllerBehavior.h" +#include "characterkinematic/PxControllerManager.h" +#include "characterkinematic/PxControllerObstacles.h" +#include "characterkinematic/PxExtended.h" + +//Cooking (data preprocessing) +#include "cooking/Pxc.h" +#include "cooking/PxConvexMeshDesc.h" +#include "cooking/PxCooking.h" +#include "cooking/PxTriangleMeshDesc.h" +#include "cooking/PxBVH33MidphaseDesc.h" +#include "cooking/PxBVH34MidphaseDesc.h" +#include "cooking/PxMidphaseDesc.h" + +//Extensions to the SDK +#include "extensions/PxDefaultStreams.h" +#include "extensions/PxDistanceJoint.h" +#include "extensions/PxExtensionsAPI.h" +#include "extensions/PxFixedJoint.h" +#include "extensions/PxJoint.h" +#include "extensions/PxJointLimit.h" +#include "extensions/PxPrismaticJoint.h" +#include "extensions/PxRevoluteJoint.h" +#include "extensions/PxRigidBodyExt.h" +#include "extensions/PxShapeExt.h" +#include "extensions/PxSimpleFactory.h" +#include "extensions/PxSmoothNormals.h" +#include "extensions/PxSphericalJoint.h" +#include "extensions/PxStringTableExt.h" +#include "extensions/PxTriangleMeshExt.h" +#include "extensions/PxConvexMeshExt.h" + +//Serialization +#include "extensions/PxSerialization.h" +#include "extensions/PxBinaryConverter.h" +#include "extensions/PxRepXSerializer.h" + +//Vehicle Simulation +#include "vehicle/PxVehicleComponents.h" +#include "vehicle/PxVehicleDrive.h" +#include "vehicle/PxVehicleDrive4W.h" +#include "vehicle/PxVehicleDriveTank.h" +#include "vehicle/PxVehicleSDK.h" +#include "vehicle/PxVehicleShaders.h" +#include "vehicle/PxVehicleTireFriction.h" +#include "vehicle/PxVehicleUpdate.h" +#include "vehicle/PxVehicleUtilControl.h" +#include "vehicle/PxVehicleUtilSetup.h" +#include "vehicle/PxVehicleUtilTelemetry.h" +#include "vehicle/PxVehicleWheels.h" +#include "vehicle/PxVehicleNoDrive.h" +#include "vehicle/PxVehicleDriveNW.h" + +//Connecting the SDK to Visual Debugger +#include "pvd/PxPvdSceneClient.h" +#include "pvd/PxPvd.h" +#include "pvd/PxPvdTransport.h" +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/PxPhysicsSerialization.h b/sources/PhysX/PhysX/include/PxPhysicsSerialization.h new file mode 100644 index 00000000..f9d657b9 --- /dev/null +++ b/sources/PhysX/PhysX/include/PxPhysicsSerialization.h @@ -0,0 +1,74 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_PX_PHYSICS_SERIALIZATION +#define PX_PHYSICS_PX_PHYSICS_SERIALIZATION + +#include "common/PxSerialFramework.h" +#include "PxPhysXConfig.h" + +#if !PX_DOXYGEN +/** +\brief Retrieves the PhysX SDK metadata. +This function is used to implement PxSerialization.dumpBinaryMetaData() and is not intended to be needed otherwise. +@see PxSerialization.dumpBinaryMetaData() +*/ +PX_C_EXPORT PX_PHYSX_CORE_API void PX_CALL_CONV PxGetPhysicsBinaryMetaData(physx::PxOutputStream& stream); + +/** +\brief Registers physics classes for serialization. +This function is used to implement PxSerialization.createSerializationRegistry() and is not intended to be needed otherwise. +@see PxSerializationRegistry +*/ +PX_C_EXPORT PX_PHYSX_CORE_API void PX_CALL_CONV PxRegisterPhysicsSerializers(physx::PxSerializationRegistry& sr); + +/** +\brief Unregisters physics classes for serialization. +This function is used in the release implementation of PxSerializationRegistry and in not intended to be used otherwise. +@see PxSerializationRegistry +*/ +PX_C_EXPORT PX_PHYSX_CORE_API void PX_CALL_CONV PxUnregisterPhysicsSerializers(physx::PxSerializationRegistry& sr); + + +/** +\brief Adds collected objects to PxPhysics. + +This function adds all objects contained in the input collection to the PxPhysics instance. This is used after deserializing +the collection, to populate the physics with inplace deserialized objects. This function is used in the implementation of +PxSerialization.createCollectionFromBinary and is not intended to be needed otherwise. +\param[in] collection Objects to add to the PxPhysics instance. + +@see PxCollection, PxSerialization.createCollectionFromBinary +*/ +PX_C_EXPORT PX_PHYSX_CORE_API void PX_CALL_CONV PxAddCollectionToPhysics(const physx::PxCollection& collection); + +#endif // !PX_DOXYGEN + +#endif // PX_PHYSICS_PX_PHYSICS_SERIALIZATION diff --git a/sources/PhysX/PhysX/include/PxPhysicsVersion.h b/sources/PhysX/PhysX/include/PxPhysicsVersion.h new file mode 100644 index 00000000..4f8c67c0 --- /dev/null +++ b/sources/PhysX/PhysX/include/PxPhysicsVersion.h @@ -0,0 +1,65 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_PHYSICS_VERSION_NUMBER_H +#define PX_PHYSICS_VERSION_NUMBER_H + +/* +VersionNumbers: The combination of these +numbers uniquely identifies the API, and should +be incremented when the SDK API changes. This may +include changes to file formats. + +This header is included in the main SDK header files +so that the entire SDK and everything that builds on it +is completely rebuilt when this file changes. Thus, +this file is not to include a frequently changing +build number. See BuildNumber.h for that. + +Each of these three values should stay below 255 because +sometimes they are stored in a byte. +*/ +/** \addtogroup foundation + @{ +*/ + +#define PX_PHYSICS_VERSION_MAJOR 4 +#define PX_PHYSICS_VERSION_MINOR 1 +#define PX_PHYSICS_VERSION_BUGFIX 1 + +/** +The constant PX_PHYSICS_VERSION is used when creating certain PhysX module objects. +This is to ensure that the application is using the same header version as the library was built with. +*/ +#define PX_PHYSICS_VERSION ((PX_PHYSICS_VERSION_MAJOR<<24) + (PX_PHYSICS_VERSION_MINOR<<16) + (PX_PHYSICS_VERSION_BUGFIX<<8) + 0) + + +#endif // PX_PHYSICS_VERSION_NUMBER_H + + /** @} */ diff --git a/sources/PhysX/PhysX/include/PxPruningStructure.h b/sources/PhysX/PhysX/include/PxPruningStructure.h new file mode 100644 index 00000000..562b5fff --- /dev/null +++ b/sources/PhysX/PhysX/include/PxPruningStructure.h @@ -0,0 +1,109 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX_PRUNING_STRUCTURE +#define PX_PHYSICS_NX_PRUNING_STRUCTURE +/** \addtogroup physics +@{ */ + +#include "PxPhysXConfig.h" +#include "common/PxBase.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + + +/** +\brief A precomputed pruning structure to accelerate scene queries against newly added actors. + +The pruning structure can be provided to #PxScene:: addActors() in which case it will get merged +directly into the scene query optimization AABB tree, thus leading to improved performance when +doing queries against the newly added actors. This applies to both static and dynamic actors. + +\note PxPruningStructure objects can be added to a collection and get serialized. +\note Adding a PxPruningStructure object to a collection will also add the actors that were used to build the pruning structure. + +\note PxPruningStructure must be released before its rigid actors. +\note PxRigidBody objects can be in one PxPruningStructure only. +\note Changing the bounds of PxRigidBody objects assigned to a pruning structure that has not been added to a scene yet will +invalidate the pruning structure. Same happens if shape scene query flags change or shape gets removed from an actor. + +@see PxScene::addActors PxCollection +*/ +class PxPruningStructure : public PxBase +{ +public: + /** + \brief Release this object. + */ + virtual void release() = 0; + + /** + \brief Retrieve rigid actors in the pruning structure. + + You can retrieve the number of rigid actor pointers by calling #getNbRigidActors() + + \param[out] userBuffer The buffer to store the actor pointers. + \param[in] bufferSize Size of provided user buffer. + \param[in] startIndex Index of first actor pointer to be retrieved + \return Number of rigid actor pointers written to the buffer. + + @see PxRigidActor + */ + virtual PxU32 getRigidActors(PxRigidActor** userBuffer, PxU32 bufferSize, PxU32 startIndex=0) const = 0; + + /** + \brief Returns the number of rigid actors in the pruning structure. + + You can use #getRigidActors() to retrieve the rigid actor pointers. + + \return Number of rigid actors in the pruning structure. + + @see PxRigidActor + */ + virtual PxU32 getNbRigidActors() const = 0; + + virtual const char* getConcreteTypeName() const { return "PxPruningStructure"; } +protected: + PX_INLINE PxPruningStructure(PxType concreteType, PxBaseFlags baseFlags) : PxBase(concreteType, baseFlags) {} + PX_INLINE PxPruningStructure(PxBaseFlags baseFlags) : PxBase(baseFlags) {} + virtual ~PxPruningStructure() {} + virtual bool isKindOf(const char* name) const { return !::strcmp("PxPruningStructure", name) || PxBase::isKindOf(name); } +}; + + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif // PX_PHYSICS_NX_PRUNING_STRUCTURE diff --git a/sources/PhysX/PhysX/include/PxQueryFiltering.h b/sources/PhysX/PhysX/include/PxQueryFiltering.h new file mode 100644 index 00000000..816ed908 --- /dev/null +++ b/sources/PhysX/PhysX/include/PxQueryFiltering.h @@ -0,0 +1,276 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX_SCENE_QUERY_FILTERING +#define PX_PHYSICS_NX_SCENE_QUERY_FILTERING +/** \addtogroup scenequery +@{ +*/ + +#include "PxPhysXConfig.h" +#include "PxFiltering.h" +#include "PxQueryReport.h" +#include "PxClient.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxShape; +class PxRigidActor; +struct PxQueryHit; + + +/** +\brief Filtering flags for scene queries. + +@see PxQueryFilterData.flags +*/ +struct PxQueryFlag +{ + enum Enum + { + eSTATIC = (1<<0), //!< Traverse static shapes + + eDYNAMIC = (1<<1), //!< Traverse dynamic shapes + + ePREFILTER = (1<<2), //!< Run the pre-intersection-test filter (see #PxQueryFilterCallback::preFilter()) + + ePOSTFILTER = (1<<3), //!< Run the post-intersection-test filter (see #PxQueryFilterCallback::postFilter()) + + eANY_HIT = (1<<4), //!< Abort traversal as soon as any hit is found and return it via callback.block. + //!< Helps query performance. Both eTOUCH and eBLOCK hitTypes are considered hits with this flag. + + eNO_BLOCK = (1<<5), //!< All hits are reported as touching. Overrides eBLOCK returned from user filters with eTOUCH. + //!< This is also an optimization hint that may improve query performance. + + eRESERVED = (1<<15) //!< Reserved for internal use + }; +}; +PX_COMPILE_TIME_ASSERT(PxQueryFlag::eSTATIC==(1<<0)); +PX_COMPILE_TIME_ASSERT(PxQueryFlag::eDYNAMIC==(1<<1)); + +/** +\brief Flags typedef for the set of bits defined in PxQueryFlag. + +*/ +typedef PxFlags PxQueryFlags; +PX_FLAGS_OPERATORS(PxQueryFlag::Enum,PxU16) + +/** +\brief Classification of scene query hits (intersections). + + - eNONE: Returning this hit type means that the hit should not be reported. + - eBLOCK: For all raycast, sweep and overlap queries the nearest eBLOCK type hit will always be returned in PxHitCallback::block member. + - eTOUCH: Whenever a raycast, sweep or overlap query was called with non-zero PxHitCallback::nbTouches and PxHitCallback::touches + parameters, eTOUCH type hits that are closer or same distance (touchDistance <= blockDistance condition) + as the globally nearest eBLOCK type hit, will be reported. + - For example, to record all hits from a raycast query, always return eTOUCH. + +All hits in overlap() queries are treated as if the intersection distance were zero. +This means the hits are unsorted and all eTOUCH hits are recorded by the callback even if an eBLOCK overlap hit was encountered. +Even though all overlap() blocking hits have zero length, only one (arbitrary) eBLOCK overlap hit is recorded in PxHitCallback::block. +All overlap() eTOUCH type hits are reported (zero touchDistance <= zero blockDistance condition). + +For raycast/sweep/overlap calls with zero touch buffer or PxHitCallback::nbTouches member, +only the closest hit of type eBLOCK is returned. All eTOUCH hits are discarded. + +@see PxQueryFilterCallback.preFilter PxQueryFilterCallback.postFilter PxScene.raycast PxScene.sweep PxScene.overlap +*/ +struct PxQueryHitType +{ + enum Enum + { + eNONE = 0, //!< the query should ignore this shape + eTOUCH = 1, //!< a hit on the shape touches the intersection geometry of the query but does not block it + eBLOCK = 2 //!< a hit on the shape blocks the query (does not block overlap queries) + }; +}; + +/** +\brief Scene query filtering data. + +Whenever the scene query intersects a shape, filtering is performed in the following order: + +\li For non-batched queries only:
If the data field is non-zero, and the bitwise-AND value of data AND the shape's +queryFilterData is zero, the shape is skipped +\li If filter callbacks are enabled in flags field (see #PxQueryFlags) they will get invoked accordingly. +\li If neither #PxQueryFlag::ePREFILTER or #PxQueryFlag::ePOSTFILTER is set, the hit defaults +to type #PxQueryHitType::eBLOCK when the value of PxHitCallback::nbTouches provided with the query is zero and to type +#PxQueryHitType::eTOUCH when PxHitCallback::nbTouches is positive. + +@see PxScene.raycast PxScene.sweep PxScene.overlap PxBatchQuery.raycast PxBatchQuery.sweep PxBatchQuery.overlap PxQueryFlag::eANY_HIT +*/ +struct PxQueryFilterData +{ + /** \brief default constructor */ + explicit PX_INLINE PxQueryFilterData() : flags(PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC) {} + + /** \brief constructor to set both filter data and filter flags */ + explicit PX_INLINE PxQueryFilterData(const PxFilterData& fd, PxQueryFlags f) : data(fd), flags(f) {} + + /** \brief constructor to set filter flags only */ + explicit PX_INLINE PxQueryFilterData(PxQueryFlags f) : flags(f) {} + + PxFilterData data; //!< Filter data associated with the scene query + PxQueryFlags flags; //!< Filter flags (see #PxQueryFlags) +}; + +/** +\brief Scene query filtering callbacks. + +Custom filtering logic for scene query intersection candidates. If an intersection candidate object passes the data based filter +(see #PxQueryFilterData), filtering callbacks are executed if requested (see #PxQueryFilterData.flags) + +\li If #PxQueryFlag::ePREFILTER is set, the preFilter function runs before exact intersection tests. +If this function returns #PxQueryHitType::eTOUCH or #PxQueryHitType::eBLOCK, exact testing is performed to +determine the intersection location. + +The preFilter function may overwrite the copy of queryFlags it receives as an argument to specify any of #PxHitFlag::eMODIFIABLE_FLAGS +on a per-shape basis. Changes apply only to the shape being filtered, and changes to other flags are ignored. + +\li If #PxQueryFlag::ePREFILTER is not set, precise intersection testing is performed using the original query's filterData.flags. + +\li If #PxQueryFlag::ePOSTFILTER is set, the postFilter function is called for each intersection to determine the touch/block status. +This overrides any touch/block status previously returned from the preFilter function for this shape. + +Filtering calls are not guaranteed to be sorted along the ray or sweep direction. + +@see PxScene.raycast PxScene.sweep PxScene.overlap PxQueryFlags PxHitFlags +*/ +class PxQueryFilterCallback +{ +public: + + /** + \brief This filter callback is executed before the exact intersection test if PxQueryFlag::ePREFILTER flag was set. + + \param[in] filterData custom filter data specified as the query's filterData.data parameter. + \param[in] shape A shape that has not yet passed the exact intersection test. + \param[in] actor The shape's actor. + \param[in,out] queryFlags scene query flags from the query's function call (only flags from PxHitFlag::eMODIFIABLE_FLAGS bitmask can be modified) + \return the updated type for this hit (see #PxQueryHitType) + */ + virtual PxQueryHitType::Enum preFilter( + const PxFilterData& filterData, const PxShape* shape, const PxRigidActor* actor, PxHitFlags& queryFlags) = 0; + + /** + \brief This filter callback is executed if the exact intersection test returned true and PxQueryFlag::ePOSTFILTER flag was set. + + \param[in] filterData custom filter data of the query + \param[in] hit Scene query hit information. faceIndex member is not valid for overlap queries. For sweep and raycast queries the hit information can be cast to #PxSweepHit and #PxRaycastHit respectively. + \return the updated hit type for this hit (see #PxQueryHitType) + */ + virtual PxQueryHitType::Enum postFilter(const PxFilterData& filterData, const PxQueryHit& hit) = 0; + + /** + \brief virtual destructor + */ + virtual ~PxQueryFilterCallback() {} +}; + +/** +\brief Batched query pre-filter shader. + +Custom filtering logic for batched query intersection candidates. If an intersection candidate object passes the data based filter (see #PxQueryFilterData), +filtering shader runs if specified in filtering flags (see #PxQueryFilterData.flags) + +\li If #PxQueryFlag::ePREFILTER is set, the preFilter shader runs before exact intersection tests. +If the shader returns #PxQueryHitType::eTOUCH or #PxQueryHitType::eBLOCK, exact testing is performed to +determine the intersection location. + +The preFilter shader may overwrite the copy of queryFlags it receives as an argument to specify any of #PxHitFlag::eMODIFIABLE_FLAGS +on a per-shape basis. Changes apply only to the shape being filtered, and changes to other flags are ignored. + +\li If #PxQueryFlag::ePREFILTER is not set, precise intersection testing is performed using the original query's filterData.flags. + +Filtering calls are not guaranteed to be sorted along the ray or sweep direction. + +\deprecated The batched query feature has been deprecated in PhysX version 3.4 + +@see PxBatchQueryDesc.preFilterShader PxQueryFilterCallback.preFilter PxBatchQueryPostFilterShader + +*/ + +/** +\param[in] queryFilterData Query filter data +\param[in] objectFilterData Object filter data +\param[in] constantBlock Global constant filter data (see #PxBatchQuery) +\param[in] constantBlockSize Size of global filter data (see #PxBatchQuery) +\param[in,out] hitFlags Per-object modifiable hit flags (only flags from PxHitFlag::eMODIFIABLE_FLAGS mask can be modified) +\return the updated hit type for this hit (see #PxQueryHitType) + +@see PxBatchQueryPostFilterShader +*/ +typedef PX_DEPRECATED PxQueryHitType::Enum (*PxBatchQueryPreFilterShader)( + PxFilterData queryFilterData, PxFilterData objectFilterData, + const void* constantBlock, PxU32 constantBlockSize, + PxHitFlags& hitFlags); + +/** +\brief Batched query post-filter shader. + +Custom filtering logic for batched query intersection candidates. If an intersection candidate object passes the data based filter (see #PxQueryFilterData), +the filtering shader run on request (see #PxQueryFilterData.flags) + +\li If #PxQueryFlag::ePOSTFILTER is set, the postFilter shader is called for each intersection to determine the touch/block status. +This overrides any touch/block status previously returned from the preFilter function for this shape. + +Filtering shaders are not in order along the query direction, rather they are processed in the order in which +candidate shapes for testing are found by PhysX' scene traversal algorithms. + +\deprecated The batched query feature has been deprecated in PhysX version 3.4 + +@see PxBatchQueryDesc.postFilterShader PxQueryFilterCallback.postFilter PxBatchQueryPreFilterShader +*/ + +/** +\param[in] queryFilterData Query filter data +\param[in] objectFilterData Object filter data +\param[in] constantBlock Global constant filter data (see #PxBatchQuery) +\param[in] constantBlockSize Size of global filter data (see #PxBatchQuery) +\param[in] hit Hit data from the prior exact intersection test. +\return the new hit type for this hit (see #PxQueryHitType) + +@see PxBatchQueryPreFilterShader +*/ + +typedef PX_DEPRECATED PxQueryHitType::Enum (*PxBatchQueryPostFilterShader)( + PxFilterData queryFilterData, PxFilterData objectFilterData, + const void* constantBlock, PxU32 constantBlockSize, + const PxQueryHit& hit); + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/PxQueryReport.h b/sources/PhysX/PhysX/include/PxQueryReport.h new file mode 100644 index 00000000..f48741ab --- /dev/null +++ b/sources/PhysX/PhysX/include/PxQueryReport.h @@ -0,0 +1,391 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX_SCENEQUERYREPORT +#define PX_PHYSICS_NX_SCENEQUERYREPORT +/** \addtogroup scenequery +@{ +*/ +#include "foundation/PxVec3.h" +#include "foundation/PxFlags.h" +#include "foundation/PxAssert.h" +#include "PxPhysXConfig.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxShape; +class PxRigidActor; + +/** +\brief Scene query and geometry query behavior flags. + +PxHitFlags are used for 3 different purposes: + +1) To request hit fields to be filled in by scene queries (such as hit position, normal, face index or UVs). +2) Once query is completed, to indicate which fields are valid (note that a query may produce more valid fields than requested). +3) To specify additional options for the narrow phase and mid-phase intersection routines. + +All these flags apply to both scene queries and geometry queries (PxGeometryQuery). + +@see PxRaycastHit PxSweepHit PxOverlapHit PxScene.raycast PxScene.sweep PxScene.overlap PxGeometryQuery PxFindFaceIndex +*/ +struct PxHitFlag +{ + enum Enum + { + ePOSITION = (1<<0), //!< "position" member of #PxQueryHit is valid + eNORMAL = (1<<1), //!< "normal" member of #PxQueryHit is valid + eUV = (1<<3), //!< "u" and "v" barycentric coordinates of #PxQueryHit are valid. Not applicable to sweep queries. + eASSUME_NO_INITIAL_OVERLAP = (1<<4), //!< Performance hint flag for sweeps when it is known upfront there's no initial overlap. + //!< NOTE: using this flag may cause undefined results if shapes are initially overlapping. + eMESH_MULTIPLE = (1<<5), //!< Report all hits for meshes rather than just the first. Not applicable to sweep queries. + eMESH_ANY = (1<<6), //!< Report any first hit for meshes. If neither eMESH_MULTIPLE nor eMESH_ANY is specified, + //!< a single closest hit will be reported for meshes. + eMESH_BOTH_SIDES = (1<<7), //!< Report hits with back faces of mesh triangles. Also report hits for raycast + //!< originating on mesh surface and facing away from the surface normal. Not applicable to sweep queries. + //!< Please refer to the user guide for heightfield-specific differences. + ePRECISE_SWEEP = (1<<8), //!< Use more accurate but slower narrow phase sweep tests. + //!< May provide better compatibility with PhysX 3.2 sweep behavior. + eMTD = (1<<9), //!< Report the minimum translation depth, normal and contact point. + eFACE_INDEX = (1<<10), //!< "face index" member of #PxQueryHit is valid + + eDEFAULT = ePOSITION|eNORMAL|eFACE_INDEX, + + /** \brief Only this subset of flags can be modified by pre-filter. Other modifications will be discarded. */ + eMODIFIABLE_FLAGS = eMESH_MULTIPLE|eMESH_BOTH_SIDES|eASSUME_NO_INITIAL_OVERLAP|ePRECISE_SWEEP + }; +}; + + +/** +\brief collection of set bits defined in PxHitFlag. + +@see PxHitFlag +*/ +PX_FLAGS_TYPEDEF(PxHitFlag, PxU16) + +/** +\brief Combines a shape pointer and the actor the shape belongs to into one memory location. + +Serves as a base class for PxQueryHit. + +@see PxQueryHit +*/ +struct PxActorShape +{ + PX_INLINE PxActorShape() : actor(NULL), shape(NULL) {} + PX_INLINE PxActorShape(PxRigidActor* a, PxShape* s) : actor(a), shape(s) {} + + PxRigidActor* actor; + PxShape* shape; +}; + + +/** +\brief Scene query hit information. +*/ +struct PxQueryHit : public PxActorShape +{ + PX_INLINE PxQueryHit() : faceIndex(0xFFFFffff) {} + + /** + Face index of touched triangle, for triangle meshes, convex meshes and height fields. + + \note This index will default to 0xFFFFffff value for overlap queries. + \note Please refer to the user guide for more details for sweep queries. + \note This index is remapped by mesh cooking. Use #PxTriangleMesh::getTrianglesRemap() to convert to original mesh index. + \note For convex meshes use #PxConvexMesh::getPolygonData() to retrieve touched polygon data. + */ + PxU32 faceIndex; +}; + +/** +\brief Scene query hit information for raycasts and sweeps returning hit position and normal information. + +::PxHitFlag flags can be passed to scene query functions, as an optimization, to cause the SDK to +only generate specific members of this structure. +*/ +struct PxLocationHit : public PxQueryHit +{ + PX_INLINE PxLocationHit() : flags(0), position(PxVec3(0)), normal(PxVec3(0)), distance(PX_MAX_REAL) {} + + /** + \note For raycast hits: true for shapes overlapping with raycast origin. + \note For sweep hits: true for shapes overlapping at zero sweep distance. + + @see PxRaycastHit PxSweepHit + */ + PX_INLINE bool hadInitialOverlap() const { return (distance <= 0.0f); } + + // the following fields are set in accordance with the #PxHitFlags + PxHitFlags flags; //!< Hit flags specifying which members contain valid values. + PxVec3 position; //!< World-space hit position (flag: #PxHitFlag::ePOSITION) + PxVec3 normal; //!< World-space hit normal (flag: #PxHitFlag::eNORMAL) + + /** + \brief Distance to hit. + \note If the eMTD flag is used, distance will be a negative value if shapes are overlapping indicating the penetration depth. + \note Otherwise, this value will be >= 0 */ + PxF32 distance; +}; + + +/** +\brief Stores results of raycast queries. + +::PxHitFlag flags can be passed to raycast function, as an optimization, to cause the SDK to only compute specified members of this +structure. + +Some members like barycentric coordinates are currently only computed for triangle meshes and height fields, but next versions +might provide them in other cases. The client code should check #flags to make sure returned values are valid. + +@see PxScene.raycast PxBatchQuery.raycast +*/ +struct PxRaycastHit : public PxLocationHit +{ + PX_INLINE PxRaycastHit() : u(0.0f), v(0.0f) {} + + // the following fields are set in accordance with the #PxHitFlags + + PxReal u, v; //!< barycentric coordinates of hit point, for triangle mesh and height field (flag: #PxHitFlag::eUV) +#if !PX_P64_FAMILY + PxU32 padTo16Bytes[3]; +#endif +}; + + +/** +\brief Stores results of overlap queries. + +@see PxScene.overlap PxBatchQuery.overlap +*/ +struct PxOverlapHit: public PxQueryHit { PxU32 padTo16Bytes; }; + + +/** +\brief Stores results of sweep queries. + +@see PxScene.sweep PxBatchQuery.sweep +*/ +struct PxSweepHit : public PxLocationHit +{ + PX_INLINE PxSweepHit() {} + + PxU32 padTo16Bytes; +}; + + +/** +\brief Describes query behavior after returning a partial query result via a callback. + +If callback returns true, traversal will continue and callback can be issued again. +If callback returns false, traversal will stop, callback will not be issued again. + +@see PxHitCallback +*/ +typedef bool PxAgain; + + +/** +\brief This callback class facilitates reporting scene query hits (intersections) to the user. + +User overrides the virtual processTouches function to receive hits in (possibly multiple) fixed size blocks. + +\note PxHitBuffer derives from this class and is used to receive touching hits in a fixed size buffer. +\note Since the compiler doesn't look in template dependent base classes when looking for non-dependent names +\note with some compilers it will be necessary to use "this->hasBlock" notation to access a parent variable +\note in a child callback class. +\note Pre-made typedef shorthands, such as ::PxRaycastCallback can be used for raycast, overlap and sweep queries. + +@see PxHitBuffer PxRaycastHit PxSweepHit PxOverlapHit PxRaycastCallback PxOverlapCallback PxSweepCallback +*/ +template +struct PxHitCallback +{ + HitType block; //!< Holds the closest blocking hit result for the query. Invalid if hasBlock is false. + bool hasBlock; //!< Set to true if there was a blocking hit during query. + + HitType* touches; //!< User specified buffer for touching hits. + + /** + \brief Size of the user specified touching hits buffer. + \note If set to 0 all hits will default to PxQueryHitType::eBLOCK, otherwise to PxQueryHitType::eTOUCH + \note Hit type returned from pre-filter overrides this default */ + PxU32 maxNbTouches; + + /** + \brief Number of touching hits returned by the query. Used with PxHitBuffer. + \note If true (PxAgain) is returned from the callback, nbTouches will be reset to 0. */ + PxU32 nbTouches; + + /** + \brief Initializes the class with user provided buffer. + + \param[in] aTouches Optional buffer for recording PxQueryHitType::eTOUCH type hits. + \param[in] aMaxNbTouches Size of touch buffer. + + \note if aTouches is NULL and aMaxNbTouches is 0, only the closest blocking hit will be recorded by the query. + \note If PxQueryFlag::eANY_HIT flag is used as a query parameter, hasBlock will be set to true and blockingHit will be used to receive the result. + \note Both eTOUCH and eBLOCK hits will be registered as hasBlock=true and stored in PxHitCallback.block when eANY_HIT flag is used. + + @see PxHitCallback.hasBlock PxHitCallback.block */ + PxHitCallback(HitType* aTouches, PxU32 aMaxNbTouches) + : hasBlock(false), touches(aTouches), maxNbTouches(aMaxNbTouches), nbTouches(0) + {} + + /** + \brief virtual callback function used to communicate query results to the user. + + This callback will always be invoked with #touches as a buffer if #touches was specified as non-NULL. + All reported touch hits are guaranteed to be closer than the closest blocking hit. + + \param[in] buffer Callback will report touch hits to the user in this buffer. This pointer will be the same as #touches. + \param[in] nbHits Number of touch hits reported in buffer. This number will not exceed #maxNbTouches. + + \note There is a significant performance penalty in case multiple touch callbacks are issued (up to 2x) + \note to avoid the penalty use a bigger buffer so that all touching hits can be reported in a single buffer. + \note If true (again) is returned from the callback, nbTouches will be reset to 0, + \note If false is returned, nbTouched will remain unchanged. + \note By the time processTouches is first called, the globally closest blocking hit is already determined, + \note values of hasBlock and block are final and all touch hits are guaranteed to be closer than the blocking hit. + \note touches and maxNbTouches can be modified inside of processTouches callback. + + \return true to continue receiving callbacks in case there are more hits or false to stop. + + @see PxAgain PxRaycastHit PxSweepHit PxOverlapHit */ + virtual PxAgain processTouches(const HitType* buffer, PxU32 nbHits) = 0; + + virtual void finalizeQuery() {} //!< Query finalization callback, called after the last processTouches callback. + + virtual ~PxHitCallback() {} + + /** \brief Returns true if any blocking or touching hits were encountered during a query. */ + PX_FORCE_INLINE bool hasAnyHits() { return (hasBlock || (nbTouches > 0)); } +}; + + +/** +\brief Returns scene query hits (intersections) to the user in a preallocated buffer. + +Will clip touch hits to maximum buffer capacity. When clipped, an arbitrary subset of touching hits will be discarded. +Overflow does not trigger warnings or errors. block and hasBlock will be valid in finalizeQuery callback and after query completion. +Touching hits are guaranteed to have closer or same distance ( <= condition) as the globally nearest blocking hit at the time any processTouches() +callback is issued. + +\note Pre-made typedef shorthands, such as ::PxRaycastBuffer can be used for raycast, overlap and sweep queries. + +@see PxHitCallback +@see PxRaycastBuffer PxOverlapBuffer PxSweepBuffer PxRaycastBufferN PxOverlapBufferN PxSweepBufferN +*/ +template +struct PxHitBuffer : public PxHitCallback +{ + /** + \brief Initializes the buffer with user memory. + + The buffer is initialized with 0 touch hits by default => query will only report a single closest blocking hit. + Use PxQueryFlag::eANY_HIT to tell the query to abort and return any first hit encoutered as blocking. + + \param[in] aTouches Optional buffer for recording PxQueryHitType::eTOUCH type hits. + \param[in] aMaxNbTouches Size of touch buffer. + + @see PxHitCallback */ + PxHitBuffer(HitType* aTouches = NULL, PxU32 aMaxNbTouches = 0) : PxHitCallback(aTouches, aMaxNbTouches) {} + + /** \brief Computes the number of any hits in this result, blocking or touching. */ + PX_INLINE PxU32 getNbAnyHits() const { return getNbTouches() + PxU32(this->hasBlock); } + /** \brief Convenience iterator used to access any hits in this result, blocking or touching. */ + PX_INLINE const HitType& getAnyHit(const PxU32 index) const { PX_ASSERT(index < getNbTouches() + PxU32(this->hasBlock)); + return index < getNbTouches() ? getTouches()[index] : this->block; } + + PX_INLINE PxU32 getNbTouches() const { return this->nbTouches; } + PX_INLINE const HitType* getTouches() const { return this->touches; } + PX_INLINE const HitType& getTouch(const PxU32 index) const { PX_ASSERT(index < getNbTouches()); return getTouches()[index]; } + PX_INLINE PxU32 getMaxNbTouches() const { return this->maxNbTouches; } + + virtual ~PxHitBuffer() {} + +protected: + // stops after the first callback + virtual PxAgain processTouches(const HitType* buffer, PxU32 nbHits) { PX_UNUSED(buffer); PX_UNUSED(nbHits); return false; } +}; + + +/** \brief Raycast query callback. */ +typedef PxHitCallback PxRaycastCallback; + +/** \brief Overlap query callback. */ +typedef PxHitCallback PxOverlapCallback; + +/** \brief Sweep query callback. */ +typedef PxHitCallback PxSweepCallback; + +/** \brief Raycast query buffer. */ +typedef PxHitBuffer PxRaycastBuffer; + +/** \brief Overlap query buffer. */ +typedef PxHitBuffer PxOverlapBuffer; + +/** \brief Sweep query buffer. */ +typedef PxHitBuffer PxSweepBuffer; + +/** \brief Returns touching raycast hits to the user in a fixed size array embedded in the buffer class. **/ +template +struct PxRaycastBufferN : public PxHitBuffer +{ + PxRaycastHit hits[N]; + PxRaycastBufferN() : PxHitBuffer(hits, N) {} +}; + +/** \brief Returns touching overlap hits to the user in a fixed size array embedded in the buffer class. **/ +template +struct PxOverlapBufferN : public PxHitBuffer +{ + PxOverlapHit hits[N]; + PxOverlapBufferN() : PxHitBuffer(hits, N) {} +}; + +/** \brief Returns touching sweep hits to the user in a fixed size array embedded in the buffer class. **/ +template +struct PxSweepBufferN : public PxHitBuffer +{ + PxSweepHit hits[N]; + PxSweepBufferN() : PxHitBuffer(hits, N) {} +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/PxRigidActor.h b/sources/PhysX/PhysX/include/PxRigidActor.h new file mode 100644 index 00000000..09852863 --- /dev/null +++ b/sources/PhysX/PhysX/include/PxRigidActor.h @@ -0,0 +1,237 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX_RIGIDACTOR +#define PX_PHYSICS_NX_RIGIDACTOR +/** \addtogroup physics +@{ +*/ + +#include "PxActor.h" +#include "PxShape.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxConstraint; +class PxMaterial; +class PxGeometry; +class PxBVHStructure; + +/** +\brief PxRigidActor represents a base class shared between dynamic and static rigid bodies in the physics SDK. + +PxRigidActor objects specify the geometry of the object by defining a set of attached shapes (see #PxShape). + +@see PxActor +*/ + +class PxRigidActor : public PxActor +{ +public: + /** + \brief Deletes the rigid actor object. + + Also releases any shapes associated with the actor. + + Releasing an actor will affect any objects that are connected to the actor (constraint shaders like joints etc.). + Such connected objects will be deleted upon scene deletion, or explicitly by the user by calling release() + on these objects. It is recommended to always remove all objects that reference actors before the actors + themselves are removed. It is not possible to retrieve list of dead connected objects. + + Sleeping: This call will awaken any sleeping actors contacting the deleted actor (directly or indirectly). + + Calls #PxActor::release() so you might want to check the documentation of that method as well. + + @see PxActor::release() + */ + virtual void release() = 0; + + +/************************************************************************************************/ +/** @name Global Pose Manipulation +*/ + + /** + \brief Retrieves the actors world space transform. + + The getGlobalPose() method retrieves the actor's current actor space to world space transformation. + + \return Global pose of object. + + @see PxRigidDynamic.setGlobalPose() PxRigidStatic.setGlobalPose() + */ + virtual PxTransform getGlobalPose() const = 0; + + /** + \brief Method for setting an actor's pose in the world. + + This method instantaneously changes the actor space to world space transformation. + + This method is mainly for dynamic rigid bodies (see #PxRigidDynamic). Calling this method on static actors is + likely to result in a performance penalty, since internal optimization structures for static actors may need to be + recomputed. In addition, moving static actors will not interact correctly with dynamic actors or joints. + + To directly control an actor's position and have it correctly interact with dynamic bodies and joints, create a dynamic + body with the PxRigidBodyFlag::eKINEMATIC flag, then use the setKinematicTarget() commands to define its path. + + Even when moving dynamic actors, exercise restraint in making use of this method. Where possible, avoid: + + \li moving actors into other actors, thus causing overlap (an invalid physical state) + + \li moving an actor that is connected by a joint to another away from the other (thus causing joint error) + + Sleeping: This call wakes dynamic actors if they are sleeping and the autowake parameter is true (default). + + \param[in] pose Transformation from the actors local frame to the global frame. Range: rigid body transform. + \param[in] autowake whether to wake the object if it is dynamic. This parameter has no effect for static or kinematic actors. If true and the current wake counter value is smaller than #PxSceneDesc::wakeCounterResetValue it will get increased to the reset value. + + @see getGlobalPose() + */ + virtual void setGlobalPose(const PxTransform& pose, bool autowake = true) = 0; + + +/************************************************************************************************/ +/** @name Shapes +*/ + + /** attach a shared shape to an actor + + This call will increment the reference count of the shape. + + \note Mass properties of dynamic rigid actors will not automatically be recomputed + to reflect the new mass distribution implied by the shape. Follow this call with a call to + the PhysX extensions method #PxRigidBodyExt::updateMassAndInertia() to do that. + + Attaching a triangle mesh, heightfield or plane geometry shape configured as eSIMULATION_SHAPE is not supported for + non-kinematic PxRigidDynamic instances. + + + Sleeping: Does NOT wake the actor up automatically. + + \param[in] shape the shape to attach. + + \return True if success. + */ + virtual bool attachShape(PxShape& shape) = 0; + + + /** detach a shape from an actor. + + This will also decrement the reference count of the PxShape, and if the reference count is zero, will cause it to be deleted. + + Sleeping: Does NOT wake the actor up automatically. + + \param[in] shape the shape to detach. + \param[in] wakeOnLostTouch Specifies whether touching objects from the previous frame should get woken up in the next frame. Only applies to PxArticulation and PxRigidActor types. + + */ + virtual void detachShape(PxShape& shape, bool wakeOnLostTouch = true) = 0; + + + /** + \brief Returns the number of shapes assigned to the actor. + + You can use #getShapes() to retrieve the shape pointers. + + \return Number of shapes associated with this actor. + + @see PxShape getShapes() + */ + virtual PxU32 getNbShapes() const = 0; + + + /** + \brief Retrieve all the shape pointers belonging to the actor. + + These are the shapes used by the actor for collision detection. + + You can retrieve the number of shape pointers by calling #getNbShapes() + + Note: Removing shapes with #PxShape::release() will invalidate the pointer of the released shape. + + \param[out] userBuffer The buffer to store the shape pointers. + \param[in] bufferSize Size of provided user buffer. + \param[in] startIndex Index of first shape pointer to be retrieved + \return Number of shape pointers written to the buffer. + + @see PxShape getNbShapes() PxShape::release() + */ + virtual PxU32 getShapes(PxShape** userBuffer, PxU32 bufferSize, PxU32 startIndex=0) const = 0; + + +/************************************************************************************************/ +/** @name Constraints +*/ + + /** + \brief Returns the number of constraint shaders attached to the actor. + + You can use #getConstraints() to retrieve the constraint shader pointers. + + \return Number of constraint shaders attached to this actor. + + @see PxConstraint getConstraints() + */ + virtual PxU32 getNbConstraints() const = 0; + + + /** + \brief Retrieve all the constraint shader pointers belonging to the actor. + + You can retrieve the number of constraint shader pointers by calling #getNbConstraints() + + Note: Removing constraint shaders with #PxConstraint::release() will invalidate the pointer of the released constraint. + + \param[out] userBuffer The buffer to store the constraint shader pointers. + \param[in] bufferSize Size of provided user buffer. + \param[in] startIndex Index of first constraint pointer to be retrieved + \return Number of constraint shader pointers written to the buffer. + + @see PxConstraint getNbConstraints() PxConstraint::release() + */ + virtual PxU32 getConstraints(PxConstraint** userBuffer, PxU32 bufferSize, PxU32 startIndex=0) const = 0; + +protected: + PX_INLINE PxRigidActor(PxType concreteType, PxBaseFlags baseFlags) : PxActor(concreteType, baseFlags) {} + PX_INLINE PxRigidActor(PxBaseFlags baseFlags) : PxActor(baseFlags) {} + virtual ~PxRigidActor() {} + virtual bool isKindOf(const char* name) const { return !::strcmp("PxRigidActor", name) || PxActor::isKindOf(name); } +}; + + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/PxRigidBody.h b/sources/PhysX/PhysX/include/PxRigidBody.h new file mode 100644 index 00000000..1d9feee0 --- /dev/null +++ b/sources/PhysX/PhysX/include/PxRigidBody.h @@ -0,0 +1,701 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX_RIGIDBODY +#define PX_PHYSICS_NX_RIGIDBODY +/** \addtogroup physics +@{ +*/ + +#include "PxRigidActor.h" +#include "PxForceMode.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + + +/** +\brief Collection of flags describing the behavior of a rigid body. + +@see PxRigidBody.setRigidBodyFlag(), PxRigidBody.getRigidBodyFlags() +*/ + +struct PxRigidBodyFlag +{ + enum Enum + { + + /** + \brief Enables kinematic mode for the actor. + + Kinematic actors are special dynamic actors that are not + influenced by forces (such as gravity), and have no momentum. They are considered to have infinite + mass and can be moved around the world using the setKinematicTarget() method. They will push + regular dynamic actors out of the way. Kinematics will not collide with static or other kinematic objects. + + Kinematic actors are great for moving platforms or characters, where direct motion control is desired. + + You can not connect Reduced joints to kinematic actors. Lagrange joints work ok if the platform + is moving with a relatively low, uniform velocity. + + Sleeping: + \li Setting this flag on a dynamic actor will put the actor to sleep and set the velocities to 0. + \li If this flag gets cleared, the current sleep state of the actor will be kept. + + \note kinematic actors are incompatible with CCD so raising this flag will automatically clear eENABLE_CCD + + @see PxRigidDynamic.setKinematicTarget() + */ + eKINEMATIC = (1<<0), //!< Enable kinematic mode for the body. + + /** + \brief Use the kinematic target transform for scene queries. + + If this flag is raised, then scene queries will treat the kinematic target transform as the current pose + of the body (instead of using the actual pose). Without this flag, the kinematic target will only take + effect with respect to scene queries after a simulation step. + + @see PxRigidDynamic.setKinematicTarget() + */ + eUSE_KINEMATIC_TARGET_FOR_SCENE_QUERIES = (1<<1), + + /** + \brief Enables swept integration for the actor. + + If this flag is raised and CCD is enabled on the scene, then this body will be simulated by the CCD system to ensure that collisions are not missed due to + high-speed motion. Note individual shape pairs still need to enable PxPairFlag::eDETECT_CCD_CONTACT in the collision filtering to enable the CCD to respond to + individual interactions. + + \note kinematic actors are incompatible with CCD so this flag will be cleared automatically when raised on a kinematic actor + + */ + eENABLE_CCD = (1<<2), //!< Enable CCD for the body. + + /** + \brief Enabled CCD in swept integration for the actor. + + If this flag is raised and CCD is enabled, CCD interactions will simulate friction. By default, friction is disabled in CCD interactions because + CCD friction has been observed to introduce some simulation artifacts. CCD friction was enabled in previous versions of the SDK. Raising this flag will result in behavior + that is a closer match for previous versions of the SDK. + + \note This flag requires PxRigidBodyFlag::eENABLE_CCD to be raised to have any effect. + */ + eENABLE_CCD_FRICTION = (1<<3), + + /** + \brief Register a rigid body for reporting pose changes by the simulation at an early stage. + + Sometimes it might be advantageous to get access to the new pose of a rigid body as early as possible and + not wait until the call to fetchResults() returns. Setting this flag will schedule the rigid body to get reported + in #PxSimulationEventCallback::onAdvance(). Please refer to the documentation of that callback to understand + the behavior and limitations of this functionality. + + @see PxSimulationEventCallback::onAdvance() + */ + eENABLE_POSE_INTEGRATION_PREVIEW = (1 << 4), + + /** + \brief Register a rigid body to dynamicly adjust contact offset based on velocity. This can be used to achieve a CCD effect. + */ + eENABLE_SPECULATIVE_CCD = (1 << 5), + + /** + \brief Permit CCD to limit maxContactImpulse. This is useful for use-cases like a destruction system but can cause visual artefacts so is not enabled by default. + */ + eENABLE_CCD_MAX_CONTACT_IMPULSE = (1 << 6), + + /** + \brief Carries over forces/accelerations between frames, rather than clearning them + */ + eRETAIN_ACCELERATIONS = (1<<7) + }; +}; + +/** +\brief collection of set bits defined in PxRigidBodyFlag. + +@see PxRigidBodyFlag +*/ +typedef PxFlags PxRigidBodyFlags; +PX_FLAGS_OPERATORS(PxRigidBodyFlag::Enum,PxU8) + +/** +\brief PxRigidBody is a base class shared between dynamic rigid body objects. + +@see PxRigidActor +*/ + +class PxRigidBody : public PxRigidActor +{ +public: + // Runtime modifications + +/************************************************************************************************/ +/** @name Mass Manipulation +*/ + + /** + \brief Sets the pose of the center of mass relative to the actor. + + \note Changing this transform will not move the actor in the world! + + \note Setting an unrealistic center of mass which is a long way from the body can make it difficult for + the SDK to solve constraints. Perhaps leading to instability and jittering bodies. + + Default: the identity transform + + \param[in] pose Mass frame offset transform relative to the actor frame. Range: rigid body transform. + + @see getCMassLocalPose() PxRigidBodyDesc.massLocalPose + */ + virtual void setCMassLocalPose(const PxTransform& pose) = 0; + + + /** + \brief Retrieves the center of mass pose relative to the actor frame. + + \return The center of mass pose relative to the actor frame. + + @see setCMassLocalPose() PxRigidBodyDesc.massLocalPose + */ + virtual PxTransform getCMassLocalPose() const = 0; + + + /** + \brief Sets the mass of a dynamic actor. + + The mass must be non-negative. + + setMass() does not update the inertial properties of the body, to change the inertia tensor + use setMassSpaceInertiaTensor() or the PhysX extensions method #PxRigidBodyExt::updateMassAndInertia(). + + \note A value of 0 is interpreted as infinite mass. + \note Values of 0 are not permitted for instances of PxArticulationLink but are permitted for instances of PxRigidDynamic. + + Default: 1.0 + + Sleeping: Does NOT wake the actor up automatically. + + \param[in] mass New mass value for the actor. Range: [0, PX_MAX_F32) + + @see getMass() PxRigidBodyDesc.mass setMassSpaceInertiaTensor() + */ + virtual void setMass(PxReal mass) = 0; + + /** + \brief Retrieves the mass of the actor. + + \note A value of 0 is interpreted as infinite mass. + + \return The mass of this actor. + + @see setMass() PxRigidBodyDesc.mass setMassSpaceInertiaTensor() + */ + virtual PxReal getMass() const = 0; + + /** + \brief Retrieves the inverse mass of the actor. + + \return The inverse mass of this actor. + + @see setMass() PxRigidBodyDesc.mass setMassSpaceInertiaTensor() + */ + virtual PxReal getInvMass() const = 0; + + /** + \brief Sets the inertia tensor, using a parameter specified in mass space coordinates. + + Note that such matrices are diagonal -- the passed vector is the diagonal. + + If you have a non diagonal world/actor space inertia tensor(3x3 matrix). Then you need to + diagonalize it and set an appropriate mass space transform. See #setCMassLocalPose(). + + The inertia tensor elements must be non-negative. + + \note A value of 0 in an element is interpreted as infinite inertia along that axis. + \note Values of 0 are not permitted for instances of PxArticulationLink but are permitted for instances of PxRigidDynamic. + + Default: (1.0, 1.0, 1.0) + + Sleeping: Does NOT wake the actor up automatically. + + \param[in] m New mass space inertia tensor for the actor. + + @see PxRigidBodyDesc.massSpaceInertia getMassSpaceInertia() setMass() setCMassLocalPose() + */ + virtual void setMassSpaceInertiaTensor(const PxVec3& m) = 0; + + /** + \brief Retrieves the diagonal inertia tensor of the actor relative to the mass coordinate frame. + + This method retrieves a mass frame inertia vector. + + \return The mass space inertia tensor of this actor. + + \note A value of 0 in an element is interpreted as infinite inertia along that axis. + + @see PxRigidBodyDesc.massSpaceInertia setMassSpaceInertiaTensor() setMass() setCMassLocalPose() + */ + virtual PxVec3 getMassSpaceInertiaTensor() const = 0; + + /** + \brief Retrieves the diagonal inverse inertia tensor of the actor relative to the mass coordinate frame. + + This method retrieves a mass frame inverse inertia vector. + + \note A value of 0 in an element is interpreted as infinite inertia along that axis. + + \return The mass space inverse inertia tensor of this actor. + + @see PxRigidBodyDesc.massSpaceInertia setMassSpaceInertiaTensor() setMass() setCMassLocalPose() + */ + virtual PxVec3 getMassSpaceInvInertiaTensor() const = 0; + + /************************************************************************************************/ + /** @name Damping + */ + + /** + \brief Sets the linear damping coefficient. + + Zero represents no damping. The damping coefficient must be nonnegative. + + Default: 0.0 + + \param[in] linDamp Linear damping coefficient. Range: [0, PX_MAX_F32) + + @see getLinearDamping() setAngularDamping() + */ + virtual void setLinearDamping(PxReal linDamp) = 0; + + /** + \brief Retrieves the linear damping coefficient. + + \return The linear damping coefficient associated with this actor. + + @see setLinearDamping() getAngularDamping() + */ + virtual PxReal getLinearDamping() const = 0; + + /** + \brief Sets the angular damping coefficient. + + Zero represents no damping. + + The angular damping coefficient must be nonnegative. + + Default: 0.05 + + \param[in] angDamp Angular damping coefficient. Range: [0, PX_MAX_F32) + + @see getAngularDamping() setLinearDamping() + */ + virtual void setAngularDamping(PxReal angDamp) = 0; + + /** + \brief Retrieves the angular damping coefficient. + + \return The angular damping coefficient associated with this actor. + + @see setAngularDamping() getLinearDamping() + */ + virtual PxReal getAngularDamping() const = 0; + + +/************************************************************************************************/ +/** @name Velocity +*/ + + + /** + \brief Retrieves the linear velocity of an actor. + + \return The linear velocity of the actor. + + @see PxRigidDynamic.setLinearVelocity() getAngularVelocity() + */ + virtual PxVec3 getLinearVelocity() const = 0; + + /** + \brief Sets the linear velocity of the actor. + + Note that if you continuously set the velocity of an actor yourself, + forces such as gravity or friction will not be able to manifest themselves, because forces directly + influence only the velocity/momentum of an actor. + + Default: (0.0, 0.0, 0.0) + + Sleeping: This call wakes the actor if it is sleeping, the autowake parameter is true (default) or the + new velocity is non-zero + + \note It is invalid to use this method if PxActorFlag::eDISABLE_SIMULATION is set. + + \param[in] linVel New linear velocity of actor. Range: velocity vector + \param[in] autowake Whether to wake the object up if it is asleep and the velocity is non-zero. If true and the current wake counter value is smaller than #PxSceneDesc::wakeCounterResetValue it will get increased to the reset value. + + @see getLinearVelocity() setAngularVelocity() + */ + virtual void setLinearVelocity(const PxVec3& linVel, bool autowake = true ) = 0; + + + + /** + \brief Retrieves the angular velocity of the actor. + + \return The angular velocity of the actor. + + @see PxRigidDynamic.setAngularVelocity() getLinearVelocity() + */ + virtual PxVec3 getAngularVelocity() const = 0; + + + /** + \brief Sets the angular velocity of the actor. + + Note that if you continuously set the angular velocity of an actor yourself, + forces such as friction will not be able to rotate the actor, because forces directly influence only the velocity/momentum. + + Default: (0.0, 0.0, 0.0) + + Sleeping: This call wakes the actor if it is sleeping, the autowake parameter is true (default) or the + new velocity is non-zero + + \note It is invalid to use this method if PxActorFlag::eDISABLE_SIMULATION is set. + + \param[in] angVel New angular velocity of actor. Range: angular velocity vector + \param[in] autowake Whether to wake the object up if it is asleep and the velocity is non-zero. If true and the current wake + counter value is smaller than #PxSceneDesc::wakeCounterResetValue it will get increased to the reset value. + + @see getAngularVelocity() setLinearVelocity() + */ + virtual void setAngularVelocity(const PxVec3& angVel, bool autowake = true ) = 0; + + /** + \brief Lets you set the maximum angular velocity permitted for this actor. + + For various internal computations, very quickly rotating actors introduce error + into the simulation, which leads to undesired results. + + With this function, you can set the maximum angular velocity permitted for this rigid body. + Higher angular velocities are clamped to this value. + + Note: The angular velocity is clamped to the set value before the solver, which means that + the limit may still be momentarily exceeded. + + Default: 100.0 + + \param[in] maxAngVel Max allowable angular velocity for actor. Range: [0, PX_MAX_F32) + + @see getMaxAngularVelocity() + */ + virtual void setMaxAngularVelocity(PxReal maxAngVel) = 0; + + /** + \brief Retrieves the maximum angular velocity permitted for this actor. + + \return The maximum allowed angular velocity for this actor. + + @see setMaxAngularVelocity + */ + virtual PxReal getMaxAngularVelocity() const = 0; + + + /** + \brief Lets you set the maximum linear velocity permitted for this actor. + + With this function, you can set the maximum linear velocity permitted for this rigid body. + Higher angular velocities are clamped to this value. + + Note: The angular velocity is clamped to the set value before the solver, which means that + the limit may still be momentarily exceeded. + + Default: PX_MAX_F32 + + \param[in] maxLinVel Max allowable linear velocity for actor. Range: [0, PX_MAX_F32) + + @see getMaxAngularVelocity() + */ + virtual void setMaxLinearVelocity(PxReal maxLinVel) = 0; + + /** + \brief Retrieves the maximum angular velocity permitted for this actor. + + \return The maximum allowed angular velocity for this actor. + + @see setMaxLinearVelocity + */ + virtual PxReal getMaxLinearVelocity() const = 0; + + +/************************************************************************************************/ +/** @name Forces +*/ + + /** + \brief Applies a force (or impulse) defined in the global coordinate frame to the actor at its center of mass. + + This will not induce a torque. + + ::PxForceMode determines if the force is to be conventional or impulsive. + + Each actor has an acceleration and a velocity change accumulator which are directly modified using the modes PxForceMode::eACCELERATION + and PxForceMode::eVELOCITY_CHANGE respectively. The modes PxForceMode::eFORCE and PxForceMode::eIMPULSE also modify these same + accumulators and are just short hand for multiplying the vector parameter by inverse mass and then using PxForceMode::eACCELERATION and + PxForceMode::eVELOCITY_CHANGE respectively. + + + \note It is invalid to use this method if the actor has not been added to a scene already or if PxActorFlag::eDISABLE_SIMULATION is set. + + \note The force modes PxForceMode::eIMPULSE and PxForceMode::eVELOCITY_CHANGE can not be applied to articulation links. + + \note if this is called on an articulation link, only the link is updated, not the entire articulation. + + \note see #PxRigidBodyExt::computeVelocityDeltaFromImpulse for details of how to compute the change in linear velocity that + will arise from the application of an impulsive force, where an impulsive force is applied force multiplied by a timestep. + + Sleeping: This call wakes the actor if it is sleeping and the autowake parameter is true (default) or the force is non-zero. + + \param[in] force Force/Impulse to apply defined in the global frame. + \param[in] mode The mode to use when applying the force/impulse(see #PxForceMode) + \param[in] autowake Specify if the call should wake up the actor if it is currently asleep. If true and the current wake counter value is smaller than #PxSceneDesc::wakeCounterResetValue it will get increased to the reset value. + + @see PxForceMode addTorque + */ + virtual void addForce(const PxVec3& force, PxForceMode::Enum mode = PxForceMode::eFORCE, bool autowake = true) = 0; + + /** + \brief Applies an impulsive torque defined in the global coordinate frame to the actor. + + ::PxForceMode determines if the torque is to be conventional or impulsive. + + Each actor has an angular acceleration and an angular velocity change accumulator which are directly modified using the modes + PxForceMode::eACCELERATION and PxForceMode::eVELOCITY_CHANGE respectively. The modes PxForceMode::eFORCE and PxForceMode::eIMPULSE + also modify these same accumulators and are just short hand for multiplying the vector parameter by inverse inertia and then + using PxForceMode::eACCELERATION and PxForceMode::eVELOCITY_CHANGE respectively. + + + \note It is invalid to use this method if the actor has not been added to a scene already or if PxActorFlag::eDISABLE_SIMULATION is set. + + \note The force modes PxForceMode::eIMPULSE and PxForceMode::eVELOCITY_CHANGE can not be applied to articulation links. + + \note if this called on an articulation link, only the link is updated, not the entire articulation. + + \note see #PxRigidBodyExt::computeVelocityDeltaFromImpulse for details of how to compute the change in angular velocity that + will arise from the application of an impulsive torque, where an impulsive torque is an applied torque multiplied by a timestep. + + Sleeping: This call wakes the actor if it is sleeping and the autowake parameter is true (default) or the torque is non-zero. + + \param[in] torque Torque to apply defined in the global frame. Range: torque vector + \param[in] mode The mode to use when applying the force/impulse(see #PxForceMode). + \param[in] autowake whether to wake up the object if it is asleep. If true and the current wake counter value is smaller than #PxSceneDesc::wakeCounterResetValue it will get increased to the reset value. + + @see PxForceMode addForce() + */ + virtual void addTorque(const PxVec3& torque, PxForceMode::Enum mode = PxForceMode::eFORCE, bool autowake = true) = 0; + + /** + \brief Clears the accumulated forces (sets the accumulated force back to zero). + + Each actor has an acceleration and a velocity change accumulator which are directly modified using the modes PxForceMode::eACCELERATION + and PxForceMode::eVELOCITY_CHANGE respectively. The modes PxForceMode::eFORCE and PxForceMode::eIMPULSE also modify these same + accumulators (see PxRigidBody::addForce() for details); therefore the effect of calling clearForce(PxForceMode::eFORCE) is equivalent to calling + clearForce(PxForceMode::eACCELERATION), and the effect of calling clearForce(PxForceMode::eIMPULSE) is equivalent to calling + clearForce(PxForceMode::eVELOCITY_CHANGE). + + ::PxForceMode determines if the cleared force is to be conventional or impulsive. + + \note The force modes PxForceMode::eIMPULSE and PxForceMode::eVELOCITY_CHANGE can not be applied to articulation links. + + \note It is invalid to use this method if the actor has not been added to a scene already or if PxActorFlag::eDISABLE_SIMULATION is set. + + \param[in] mode The mode to use when clearing the force/impulse(see #PxForceMode) + + @see PxForceMode addForce + */ + virtual void clearForce(PxForceMode::Enum mode = PxForceMode::eFORCE) = 0; + + /** + \brief Clears the impulsive torque defined in the global coordinate frame to the actor. + + ::PxForceMode determines if the cleared torque is to be conventional or impulsive. + + Each actor has an angular acceleration and a velocity change accumulator which are directly modified using the modes PxForceMode::eACCELERATION + and PxForceMode::eVELOCITY_CHANGE respectively. The modes PxForceMode::eFORCE and PxForceMode::eIMPULSE also modify these same + accumulators (see PxRigidBody::addTorque() for details); therefore the effect of calling clearTorque(PxForceMode::eFORCE) is equivalent to calling + clearTorque(PxForceMode::eACCELERATION), and the effect of calling clearTorque(PxForceMode::eIMPULSE) is equivalent to calling + clearTorque(PxForceMode::eVELOCITY_CHANGE). + + \note The force modes PxForceMode::eIMPULSE and PxForceMode::eVELOCITY_CHANGE can not be applied to articulation links. + + \note It is invalid to use this method if the actor has not been added to a scene already or if PxActorFlag::eDISABLE_SIMULATION is set. + + \param[in] mode The mode to use when clearing the force/impulse(see #PxForceMode). + + @see PxForceMode addTorque + */ + virtual void clearTorque(PxForceMode::Enum mode = PxForceMode::eFORCE) = 0; + + + /** + \brief Sets the impulsive force and torque defined in the global coordinate frame to the actor. + + ::PxForceMode determines if the cleared torque is to be conventional or impulsive. + + \note The force modes PxForceMode::eIMPULSE and PxForceMode::eVELOCITY_CHANGE can not be applied to articulation links. + + \note It is invalid to use this method if the actor has not been added to a scene already or if PxActorFlag::eDISABLE_SIMULATION is set. + + @see PxForceMode addTorque + */ + virtual void setForceAndTorque(const PxVec3& force, const PxVec3& torque, PxForceMode::Enum mode = PxForceMode::eFORCE) = 0; + + /** + \brief Raises or clears a particular rigid body flag. + + See the list of flags #PxRigidBodyFlag + + Default: no flags are set + + Sleeping: Does NOT wake the actor up automatically. + + \param[in] flag The PxRigidBody flag to raise(set) or clear. See #PxRigidBodyFlag. + \param[in] value The new boolean value for the flag. + + @see PxRigidBodyFlag getRigidBodyFlags() + */ + + virtual void setRigidBodyFlag(PxRigidBodyFlag::Enum flag, bool value) = 0; + virtual void setRigidBodyFlags(PxRigidBodyFlags inFlags) = 0; + + /** + \brief Reads the PxRigidBody flags. + + See the list of flags #PxRigidBodyFlag + + \return The values of the PxRigidBody flags. + + @see PxRigidBodyFlag setRigidBodyFlag() + */ + virtual PxRigidBodyFlags getRigidBodyFlags() const = 0; + + /** + \brief Sets the CCD minimum advance coefficient. + + The CCD minimum advance coefficient is a value in the range [0, 1] that is used to control the minimum amount of time a body is integrated when + it has a CCD contact. The actual minimum amount of time that is integrated depends on various properties, including the relative speed and collision shapes + of the bodies involved in the contact. From these properties, a numeric value is calculated that determines the maximum distance (and therefore maximum time) + which these bodies could be integrated forwards that would ensure that these bodies did not pass through each-other. This value is then scaled by CCD minimum advance + coefficient to determine the amount of time that will be consumed in the CCD pass. + + Things to consider: + A large value (approaching 1) ensures that the objects will always advance some time. However, larger values increase the chances of objects gently drifting through each-other in + scenes which the constraint solver can't converge, e.g. scenes where an object is being dragged through a wall with a constraint. + A value of 0 ensures that the pair of objects stop at the exact time-of-impact and will not gently drift through each-other. However, with very small/thin objects initially in + contact, this can lead to a large amount of time being dropped and increases the chances of jamming. Jamming occurs when the an object is persistently in contact with an object + such that the time-of-impact is 0, which results in no time being advanced for those objects in that CCD pass. + + The chances of jamming can be reduced by increasing the number of CCD mass @see PxSceneDesc.ccdMaxPasses. However, increasing this number increases the CCD overhead. + + \param[in] advanceCoefficient The CCD min advance coefficient. Range: [0, 1] Default: 0.15 + */ + + virtual void setMinCCDAdvanceCoefficient(PxReal advanceCoefficient) = 0; + + /** + \brief Gets the CCD minimum advance coefficient. + + \return The value of the CCD min advance coefficient. + + @see setMinCCDAdvanceCoefficient + + */ + + virtual PxReal getMinCCDAdvanceCoefficient() const = 0; + + + /** + \brief Sets the maximum depenetration velocity permitted to be introduced by the solver. + This value controls how much velocity the solver can introduce to correct for penetrations in contacts. + \param[in] biasClamp The maximum velocity to de-penetrate by Range: (0, PX_MAX_F32]. + */ + virtual void setMaxDepenetrationVelocity(PxReal biasClamp) = 0; + + /** + \brief Returns the maximum depenetration velocity the solver is permitted to introduced. + This value controls how much velocity the solver can introduce to correct for penetrations in contacts. + \return The maximum penetration bias applied by the solver. + */ + virtual PxReal getMaxDepenetrationVelocity() const = 0; + + + /** + \brief Sets a limit on the impulse that may be applied at a contact. The maximum impulse at a contact between two dynamic or kinematic + bodies will be the minimum of the two limit values. For a collision between a static and a dynamic body, the impulse is limited + by the value for the dynamic body. + + \param[in] maxImpulse the maximum contact impulse. Range: [0, PX_MAX_F32] Default: PX_MAX_F32 + + @see getMaxContactImpulse + */ + virtual void setMaxContactImpulse(PxReal maxImpulse) = 0; + + /** + \brief Returns the maximum impulse that may be applied at a contact. + + \return The maximum impulse that may be applied at a contact + + @see setMaxContactImpulse + */ + virtual PxReal getMaxContactImpulse() const = 0; + + /** + \brief Returns the island node index that only for internal use only + + \return The island node index that only for internal use only + */ + virtual PxU32 getInternalIslandNodeIndex() const = 0; + + +protected: + PX_INLINE PxRigidBody(PxType concreteType, PxBaseFlags baseFlags) : PxRigidActor(concreteType, baseFlags) {} + PX_INLINE PxRigidBody(PxBaseFlags baseFlags) : PxRigidActor(baseFlags) {} + virtual ~PxRigidBody() {} + virtual bool isKindOf(const char* name)const { return !::strcmp("PxRigidBody", name) || PxRigidActor::isKindOf(name); } +}; + + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/PxRigidDynamic.h b/sources/PhysX/PhysX/include/PxRigidDynamic.h new file mode 100644 index 00000000..84cb6606 --- /dev/null +++ b/sources/PhysX/PhysX/include/PxRigidDynamic.h @@ -0,0 +1,388 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX_RIGIDDYNAMIC +#define PX_PHYSICS_NX_RIGIDDYNAMIC +/** \addtogroup physics +@{ +*/ + +#include "PxRigidBody.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + + +/** +\brief Collection of flags providing a mechanism to lock motion along/around a specific axis. + +@see PxRigidDynamic.setRigidDynamicLockFlag(), PxRigidBody.getRigidDynamicLockFlags() +*/ +struct PxRigidDynamicLockFlag +{ + enum Enum + { + eLOCK_LINEAR_X = (1 << 0), + eLOCK_LINEAR_Y = (1 << 1), + eLOCK_LINEAR_Z = (1 << 2), + eLOCK_ANGULAR_X = (1 << 3), + eLOCK_ANGULAR_Y = (1 << 4), + eLOCK_ANGULAR_Z = (1 << 5) + }; +}; + +typedef PxFlags PxRigidDynamicLockFlags; +PX_FLAGS_OPERATORS(PxRigidDynamicLockFlag::Enum, PxU8) + +/** +\brief PxRigidDynamic represents a dynamic rigid simulation object in the physics SDK. + +

Creation

+Instances of this class are created by calling #PxPhysics::createRigidDynamic() and deleted with #release(). + + +

Visualizations

+\li #PxVisualizationParameter::eACTOR_AXES +\li #PxVisualizationParameter::eBODY_AXES +\li #PxVisualizationParameter::eBODY_MASS_AXES +\li #PxVisualizationParameter::eBODY_LIN_VELOCITY +\li #PxVisualizationParameter::eBODY_ANG_VELOCITY + +@see PxRigidBody PxPhysics.createRigidDynamic() release() +*/ + +class PxRigidDynamic : public PxRigidBody +{ +public: + // Runtime modifications + + +/************************************************************************************************/ +/** @name Kinematic Actors +*/ + + /** + \brief Moves kinematically controlled dynamic actors through the game world. + + You set a dynamic actor to be kinematic using the PxRigidBodyFlag::eKINEMATIC flag + with setRigidBodyFlag(). + + The move command will result in a velocity that will move the body into + the desired pose. After the move is carried out during a single time step, + the velocity is returned to zero. Thus, you must continuously call + this in every time step for kinematic actors so that they move along a path. + + This function simply stores the move destination until the next simulation + step is processed, so consecutive calls will simply overwrite the stored target variable. + + The motion is always fully carried out. + + \note It is invalid to use this method if the actor has not been added to a scene already or if PxActorFlag::eDISABLE_SIMULATION is set. + + Sleeping: This call wakes the actor if it is sleeping and will set the wake counter to #PxSceneDesc::wakeCounterResetValue. + + \param[in] destination The desired pose for the kinematic actor, in the global frame. Range: rigid body transform. + + @see getKinematicTarget() PxRigidBodyFlag setRigidBodyFlag() + */ + virtual void setKinematicTarget(const PxTransform& destination) = 0; + + /** + \brief Get target pose of a kinematically controlled dynamic actor. + + \param[out] target Transform to write the target pose to. Only valid if the method returns true. + \return True if the actor is a kinematically controlled dynamic and the target has been set, else False. + + @see setKinematicTarget() PxRigidBodyFlag setRigidBodyFlag() + */ + virtual bool getKinematicTarget(PxTransform& target) const = 0; + + +/************************************************************************************************/ +/** @name Sleeping +*/ + + /** + \brief Returns true if this body is sleeping. + + When an actor does not move for a period of time, it is no longer simulated in order to save time. This state + is called sleeping. However, because the object automatically wakes up when it is either touched by an awake object, + or one of its properties is changed by the user, the entire sleep mechanism should be transparent to the user. + + In general, a dynamic rigid actor is guaranteed to be awake if at least one of the following holds: + + \li The wake counter is positive (see #setWakeCounter()). + \li The linear or angular velocity is non-zero. + \li A non-zero force or torque has been applied. + + If a dynamic rigid actor is sleeping, the following state is guaranteed: + + \li The wake counter is zero. + \li The linear and angular velocity is zero. + \li There is no force update pending. + + When an actor gets inserted into a scene, it will be considered asleep if all the points above hold, else it will be treated as awake. + + If an actor is asleep after the call to PxScene::fetchResults() returns, it is guaranteed that the pose of the actor + was not changed. You can use this information to avoid updating the transforms of associated objects. + + \note A kinematic actor is asleep unless a target pose has been set (in which case it will stay awake until the end of the next + simulation step where no target pose has been set anymore). The wake counter will get set to zero or to the reset value + #PxSceneDesc::wakeCounterResetValue in the case where a target pose has been set to be consistent with the definitions above. + + \note It is invalid to use this method if the actor has not been added to a scene already. + + \return True if the actor is sleeping. + + @see isSleeping() wakeUp() putToSleep() getSleepThreshold() + */ + virtual bool isSleeping() const = 0; + + + /** + \brief Sets the mass-normalized kinetic energy threshold below which an actor may go to sleep. + + Actors whose kinetic energy divided by their mass is below this threshold will be candidates for sleeping. + + Default: 5e-5f * PxTolerancesScale::speed * PxTolerancesScale::speed + + \param[in] threshold Energy below which an actor may go to sleep. Range: [0, PX_MAX_F32) + + @see isSleeping() getSleepThreshold() wakeUp() putToSleep() PxTolerancesScale + */ + virtual void setSleepThreshold(PxReal threshold) = 0; + + /** + \brief Returns the mass-normalized kinetic energy below which an actor may go to sleep. + + \return The energy threshold for sleeping. + + @see isSleeping() wakeUp() putToSleep() setSleepThreshold() + */ + virtual PxReal getSleepThreshold() const = 0; + + /** + \brief Sets the mass-normalized kinetic energy threshold below which an actor may participate in stabilization. + + Actors whose kinetic energy divided by their mass is above this threshold will not participate in stabilization. + + This value has no effect if PxSceneFlag::eENABLE_STABILIZATION was not enabled on the PxSceneDesc. + + Default: 1e-5f * PxTolerancesScale::speed * PxTolerancesScale::speed + + \param[in] threshold Energy below which an actor may participate in stabilization. Range: [0,inf) + + @see getStabilizationThreshold() PxSceneFlag::eENABLE_STABILIZATION + */ + virtual void setStabilizationThreshold(PxReal threshold) = 0; + + /** + \brief Returns the mass-normalized kinetic energy below which an actor may participate in stabilization. + + Actors whose kinetic energy divided by their mass is above this threshold will not participate in stabilization. + + \return The energy threshold for participating in stabilization. + + @see setStabilizationThreshold() PxSceneFlag::eENABLE_STABILIZATION + */ + virtual PxReal getStabilizationThreshold() const = 0; + + + /** + \brief Reads the PxRigidDynamic lock flags. + + See the list of flags #PxRigidDynamicLockFlag + + \return The values of the PxRigidDynamicLock flags. + + @see PxRigidDynamicLockFlag setRigidDynamicLockFlag() + */ + virtual PxRigidDynamicLockFlags getRigidDynamicLockFlags() const = 0; + + /** + \brief Raises or clears a particular rigid dynamic lock flag. + + See the list of flags #PxRigidDynamicLockFlag + + Default: no flags are set + + + \param[in] flag The PxRigidDynamicLockBody flag to raise(set) or clear. See #PxRigidBodyFlag. + \param[in] value The new boolean value for the flag. + + @see PxRigidDynamicLockFlag getRigidDynamicLockFlags() + */ + virtual void setRigidDynamicLockFlag(PxRigidDynamicLockFlag::Enum flag, bool value) = 0; + virtual void setRigidDynamicLockFlags(PxRigidDynamicLockFlags flags) = 0; + + + + /** + \brief Sets the wake counter for the actor. + + The wake counter value determines the minimum amount of time until the body can be put to sleep. Please note + that a body will not be put to sleep if the energy is above the specified threshold (see #setSleepThreshold()) + or if other awake bodies are touching it. + + \note Passing in a positive value will wake the actor up automatically. + + \note It is invalid to use this method for kinematic actors since the wake counter for kinematics is defined + based on whether a target pose has been set (see the comment in #isSleeping()). + + \note It is invalid to use this method if PxActorFlag::eDISABLE_SIMULATION is set. + + Default: 0.4 (which corresponds to 20 frames for a time step of 0.02) + + \param[in] wakeCounterValue Wake counter value. Range: [0, PX_MAX_F32) + + @see isSleeping() getWakeCounter() + */ + virtual void setWakeCounter(PxReal wakeCounterValue) = 0; + + /** + \brief Returns the wake counter of the actor. + + \return The wake counter of the actor. + + @see isSleeping() setWakeCounter() + */ + virtual PxReal getWakeCounter() const = 0; + + /** + \brief Wakes up the actor if it is sleeping. + + The actor will get woken up and might cause other touching actors to wake up as well during the next simulation step. + + \note This will set the wake counter of the actor to the value specified in #PxSceneDesc::wakeCounterResetValue. + + \note It is invalid to use this method if the actor has not been added to a scene already or if PxActorFlag::eDISABLE_SIMULATION is set. + + \note It is invalid to use this method for kinematic actors since the sleep state for kinematics is defined + based on whether a target pose has been set (see the comment in #isSleeping()). + + @see isSleeping() putToSleep() + */ + virtual void wakeUp() = 0; + + /** + \brief Forces the actor to sleep. + + The actor will stay asleep during the next simulation step if not touched by another non-sleeping actor. + + \note Any applied force will be cleared and the velocity and the wake counter of the actor will be set to 0. + + \note It is invalid to use this method if the actor has not been added to a scene already or if PxActorFlag::eDISABLE_SIMULATION is set. + + \note It is invalid to use this method for kinematic actors since the sleep state for kinematics is defined + based on whether a target pose has been set (see the comment in #isSleeping()). + + @see isSleeping() wakeUp() + */ + virtual void putToSleep() = 0; + +/************************************************************************************************/ + + /** + \brief Sets the solver iteration counts for the body. + + The solver iteration count determines how accurately joints and contacts are resolved. + If you are having trouble with jointed bodies oscillating and behaving erratically, then + setting a higher position iteration count may improve their stability. + + If intersecting bodies are being depenetrated too violently, increase the number of velocity + iterations. More velocity iterations will drive the relative exit velocity of the intersecting + objects closer to the correct value given the restitution. + + Default: 4 position iterations, 1 velocity iteration + + \param[in] minPositionIters Number of position iterations the solver should perform for this body. Range: [1,255] + \param[in] minVelocityIters Number of velocity iterations the solver should perform for this body. Range: [1,255] + + @see getSolverIterationCounts() + */ + virtual void setSolverIterationCounts(PxU32 minPositionIters, PxU32 minVelocityIters = 1) = 0; + + /** + \brief Retrieves the solver iteration counts. + + @see setSolverIterationCounts() + */ + virtual void getSolverIterationCounts(PxU32& minPositionIters, PxU32& minVelocityIters) const = 0; + + /** + \brief Retrieves the force threshold for contact reports. + + The contact report threshold is a force threshold. If the force between + two actors exceeds this threshold for either of the two actors, a contact report + will be generated according to the contact report threshold flags provided by + the filter shader/callback. + See #PxPairFlag. + + The threshold used for a collision between a dynamic actor and the static environment is + the threshold of the dynamic actor, and all contacts with static actors are summed to find + the total normal force. + + Default: PX_MAX_F32 + + \return Force threshold for contact reports. + + @see setContactReportThreshold PxPairFlag PxSimulationFilterShader PxSimulationFilterCallback + */ + virtual PxReal getContactReportThreshold() const = 0; + + /** + \brief Sets the force threshold for contact reports. + + See #getContactReportThreshold(). + + \param[in] threshold Force threshold for contact reports. Range: [0, PX_MAX_F32) + + @see getContactReportThreshold PxPairFlag + */ + virtual void setContactReportThreshold(PxReal threshold) = 0; + + virtual const char* getConcreteTypeName() const { return "PxRigidDynamic"; } + +protected: + PX_INLINE PxRigidDynamic(PxType concreteType, PxBaseFlags baseFlags) : PxRigidBody(concreteType, baseFlags) {} + PX_INLINE PxRigidDynamic(PxBaseFlags baseFlags) : PxRigidBody(baseFlags) {} + virtual ~PxRigidDynamic() {} + virtual bool isKindOf(const char* name) const { return !::strcmp("PxRigidDynamic", name) || PxRigidBody::isKindOf(name); } + +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/PxRigidStatic.h b/sources/PhysX/PhysX/include/PxRigidStatic.h new file mode 100644 index 00000000..e5fbd650 --- /dev/null +++ b/sources/PhysX/PhysX/include/PxRigidStatic.h @@ -0,0 +1,77 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX_RIGIDSTATIC +#define PX_PHYSICS_NX_RIGIDSTATIC +/** \addtogroup physics +@{ +*/ + +#include "PxPhysXConfig.h" +#include "PxRigidActor.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief PxRigidStatic represents a static rigid body simulation object in the physics SDK. + +PxRigidStatic objects are static rigid physics entities. They shall be used to define solid objects which are fixed in the world. + +

Creation

+Instances of this class are created by calling #PxPhysics::createRigidStatic() and deleted with #release(). + +

Visualizations

+\li #PxVisualizationParameter::eACTOR_AXES + +@see PxRigidActor PxPhysics.createRigidStatic() release() +*/ + +class PxRigidStatic : public PxRigidActor +{ +public: + virtual const char* getConcreteTypeName() const { return "PxRigidStatic"; } + +protected: + PX_INLINE PxRigidStatic(PxType concreteType, PxBaseFlags baseFlags) : PxRigidActor(concreteType, baseFlags) {} + PX_INLINE PxRigidStatic(PxBaseFlags baseFlags) : PxRigidActor(baseFlags) {} + virtual ~PxRigidStatic() {} + virtual bool isKindOf(const char* name) const { return !::strcmp("PxRigidStatic", name) || PxRigidActor::isKindOf(name); } + +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/PxScene.h b/sources/PhysX/PhysX/include/PxScene.h new file mode 100644 index 00000000..ebe579f0 --- /dev/null +++ b/sources/PhysX/PhysX/include/PxScene.h @@ -0,0 +1,1682 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX_SCENE +#define PX_PHYSICS_NX_SCENE +/** \addtogroup physics +@{ +*/ + +#include "PxVisualizationParameter.h" +#include "PxSceneDesc.h" +#include "PxSimulationStatistics.h" +#include "PxQueryReport.h" +#include "PxQueryFiltering.h" +#include "PxClient.h" +#include "task/PxTask.h" + +#include "pvd/PxPvdSceneClient.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxRigidStatic; +class PxRigidDynamic; +class PxConstraint; +class PxMaterial; +class PxSimulationEventCallback; +class PxPhysics; +class PxBatchQueryDesc; +class PxBatchQuery; +class PxAggregate; +class PxRenderBuffer; + +class PxSphereGeometry; +class PxBoxGeometry; +class PxCapsuleGeometry; + +class PxPruningStructure; +class PxBVHStructure; +struct PxContactPairHeader; + +typedef PxU8 PxDominanceGroup; + +class PxPvdSceneClient; + +/** +\brief Expresses the dominance relationship of a contact. +For the time being only three settings are permitted: + +(1, 1), (0, 1), and (1, 0). + +@see getDominanceGroup() PxDominanceGroup PxScene::setDominanceGroupPair() +*/ +struct PxDominanceGroupPair +{ + PxDominanceGroupPair(PxU8 a, PxU8 b) + : dominance0(a), dominance1(b) {} + PxU8 dominance0; + PxU8 dominance1; +}; + + +/** +\brief Identifies each type of actor for retrieving actors from a scene. + +\note #PxArticulationLink objects are not supported. Use the #PxArticulation object to retrieve all its links. + +@see PxScene::getActors(), PxScene::getNbActors() +*/ +struct PxActorTypeFlag +{ + enum Enum + { + /** + \brief A static rigid body + @see PxRigidStatic + */ + eRIGID_STATIC = (1 << 0), + + /** + \brief A dynamic rigid body + @see PxRigidDynamic + */ + eRIGID_DYNAMIC = (1 << 1) + }; +}; + +/** +\brief Collection of set bits defined in PxActorTypeFlag. + +@see PxActorTypeFlag +*/ +typedef PxFlags PxActorTypeFlags; +PX_FLAGS_OPERATORS(PxActorTypeFlag::Enum,PxU16) + +/** +\brief single hit cache for scene queries. + +If a cache object is supplied to a scene query, the cached actor/shape pair is checked for intersection first. +\note Filters are not executed for the cached shape. +\note If intersection is found, the hit is treated as blocking. +\note Typically actor and shape from the last PxHitCallback.block query result is used as a cached actor/shape pair. +\note Using past touching hits as cache will produce incorrect behavior since the cached hit will always be treated as blocking. +\note Cache is only used if no touch buffer was provided, for single nearest blocking hit queries and queries using eANY_HIT flag. +\note if non-zero touch buffer was provided, cache will be ignored + +\note It is the user's responsibility to ensure that the shape and actor are valid, so care must be taken +when deleting shapes to invalidate cached references. + +The faceIndex field is an additional hint for a mesh or height field which is not currently used. + +@see PxScene.raycast +*/ +struct PxQueryCache +{ + /** + \brief constructor sets to default + */ + PX_INLINE PxQueryCache() : shape(NULL), actor(NULL), faceIndex(0xffffffff) {} + + /** + \brief constructor to set properties + */ + PX_INLINE PxQueryCache(PxShape* s, PxU32 findex) : shape(s), actor(NULL), faceIndex(findex) {} + + PxShape* shape; //!< Shape to test for intersection first + PxRigidActor* actor; //!< Actor to which the shape belongs + PxU32 faceIndex; //!< Triangle index to test first - NOT CURRENTLY SUPPORTED +}; + +/** + \brief A scene is a collection of bodies and constraints which can interact. + + The scene simulates the behavior of these objects over time. Several scenes may exist + at the same time, but each body or constraint is specific to a scene + -- they may not be shared. + + @see PxSceneDesc PxPhysics.createScene() release() +*/ +class PxScene +{ + protected: + + /************************************************************************************************/ + + /** @name Basics + */ + //@{ + + PxScene(): userData(0) {} + virtual ~PxScene() {} + + public: + + /** + \brief Deletes the scene. + + Removes any actors and constraint shaders from this scene + (if the user hasn't already done so). + + Be sure to not keep a reference to this object after calling release. + Avoid release calls while the scene is simulating (in between simulate() and fetchResults() calls). + + @see PxPhysics.createScene() + */ + virtual void release() = 0; + + /** + \brief Sets a scene flag. You can only set one flag at a time. + + \note Not all flags are mutable and changing some will result in an error. Please check #PxSceneFlag to see which flags can be changed. + + @see PxSceneFlag + */ + virtual void setFlag(PxSceneFlag::Enum flag, bool value) = 0; + + /** + \brief Get the scene flags. + + \return The scene flags. See #PxSceneFlag + + @see PxSceneFlag + */ + virtual PxSceneFlags getFlags() const = 0; + + + /** + \brief Set new scene limits. + + \note Increase the maximum capacity of various data structures in the scene. The new capacities will be + at least as large as required to deal with the objects currently in the scene. Further, these values + are for preallocation and do not represent hard limits. + + \param[in] limits Scene limits. + @see PxSceneLimits + */ + virtual void setLimits(const PxSceneLimits& limits) = 0; + + /** + \brief Get current scene limits. + \return Current scene limits. + @see PxSceneLimits + */ + virtual PxSceneLimits getLimits() const = 0; + + + /** + \brief Call this method to retrieve the Physics SDK. + + \return The physics SDK this scene is associated with. + + @see PxPhysics + */ + virtual PxPhysics& getPhysics() = 0; + + /** + \brief Retrieves the scene's internal timestamp, increased each time a simulation step is completed. + + \return scene timestamp + */ + virtual PxU32 getTimestamp() const = 0; + + + //@} + /************************************************************************************************/ + + /** @name Add/Remove Contained Objects + */ + //@{ + /** + \brief Adds an articulation to this scene. + + \note If the articulation is already assigned to a scene (see #PxArticulation::getScene), the call is ignored and an error is issued. + + \param[in] articulation Articulation to add to scene. See #PxArticulation + + @see PxArticulation + */ + virtual void addArticulation(PxArticulationBase& articulation) = 0; + + /** + \brief Removes an articulation from this scene. + + \note If the articulation is not part of this scene (see #PxArticulation::getScene), the call is ignored and an error is issued. + + \note If the articulation is in an aggregate it will be removed from the aggregate. + + \param[in] articulation Articulation to remove from scene. See #PxArticulation + \param[in] wakeOnLostTouch Specifies whether touching objects from the previous frame should get woken up in the next frame. Only applies to PxArticulation and PxRigidActor types. + + @see PxArticulation, PxAggregate + */ + virtual void removeArticulation(PxArticulationBase& articulation, bool wakeOnLostTouch = true) = 0; + + + //@} + /************************************************************************************************/ + + + /** + \brief Adds an actor to this scene. + + \note If the actor is already assigned to a scene (see #PxActor::getScene), the call is ignored and an error is issued. + \note If the actor has an invalid constraint, in checked builds the call is ignored and an error is issued. + + \note You can not add individual articulation links (see #PxArticulationLink) to the scene. Use #addArticulation() instead. + + \note If the actor is a PxRigidActor then each assigned PxConstraint object will get added to the scene automatically if + it connects to another actor that is part of the scene already. + + \note When BVHStructure is provided the actor shapes are grouped together. + The scene query pruning structure inside PhysX SDK will store/update one + bound per actor. The scene queries against such an actor will query actor + bounds and then make a local space query against the provided BVH structure, which is in + actor's local space. + + \param[in] actor Actor to add to scene. + \param[in] bvhStructure BVHStructure for actor shapes. + + @see PxActor, PxConstraint::isValid(), PxBVHStructure + */ + virtual void addActor(PxActor& actor, const PxBVHStructure* bvhStructure = NULL) = 0; + + /** + \brief Adds actors to this scene. + + \note If one of the actors is already assigned to a scene (see #PxActor::getScene), the call is ignored and an error is issued. + + \note You can not add individual articulation links (see #PxArticulationLink) to the scene. Use #addArticulation() instead. + + \note If an actor in the array contains an invalid constraint, in checked builds the call is ignored and an error is issued. + \note If an actor in the array is a PxRigidActor then each assigned PxConstraint object will get added to the scene automatically if + it connects to another actor that is part of the scene already. + + \note this method is optimized for high performance, and does not support buffering. It may not be called during simulation. + + \param[in] actors Array of actors to add to scene. + \param[in] nbActors Number of actors in the array. + + @see PxActor, PxConstraint::isValid() + */ + virtual void addActors(PxActor*const* actors, PxU32 nbActors) = 0; + + /** + \brief Adds a pruning structure together with its actors to this scene. + + \note If an actor in the pruning structure contains an invalid constraint, in checked builds the call is ignored and an error is issued. + \note For all actors in the pruning structure each assigned PxConstraint object will get added to the scene automatically if + it connects to another actor that is part of the scene already. + + \note This method is optimized for high performance, and does not support buffering. It may not be called during simulation. + + \note Merging a PxPruningStructure into an active scene query optimization AABB tree might unbalance the tree. A typical use case for + PxPruningStructure is a large world scenario where blocks of closely positioned actors get streamed in. The merge process finds the + best node in the active scene query optimization AABB tree and inserts the PxPruningStructure. Therefore using PxPruningStructure + for actors scattered throughout the world will result in an unbalanced tree. + + \param[in] pruningStructure Pruning structure for a set of actors. + + @see PxPhysics::createPruningStructure, PxPruningStructure + */ + virtual void addActors(const PxPruningStructure& pruningStructure) = 0; + + /** + \brief Removes an actor from this scene. + + \note If the actor is not part of this scene (see #PxActor::getScene), the call is ignored and an error is issued. + + \note You can not remove individual articulation links (see #PxArticulationLink) from the scene. Use #removeArticulation() instead. + + \note If the actor is a PxRigidActor then all assigned PxConstraint objects will get removed from the scene automatically. + + \note If the actor is in an aggregate it will be removed from the aggregate. + + \param[in] actor Actor to remove from scene. + \param[in] wakeOnLostTouch Specifies whether touching objects from the previous frame should get woken up in the next frame. Only applies to PxArticulation and PxRigidActor types. + + @see PxActor, PxAggregate + */ + virtual void removeActor(PxActor& actor, bool wakeOnLostTouch = true) = 0; + + /** + \brief Removes actors from this scene. + + \note If some actor is not part of this scene (see #PxActor::getScene), the actor remove is ignored and an error is issued. + + \note You can not remove individual articulation links (see #PxArticulationLink) from the scene. Use #removeArticulation() instead. + + \note If the actor is a PxRigidActor then all assigned PxConstraint objects will get removed from the scene automatically. + + \param[in] actors Array of actors to add to scene. + \param[in] nbActors Number of actors in the array. + \param[in] wakeOnLostTouch Specifies whether touching objects from the previous frame should get woken up in the next frame. Only applies to PxArticulation and PxRigidActor types. + + @see PxActor + */ + virtual void removeActors(PxActor*const* actors, PxU32 nbActors, bool wakeOnLostTouch = true) = 0; + + /** + \brief Adds an aggregate to this scene. + + \note If the aggregate is already assigned to a scene (see #PxAggregate::getScene), the call is ignored and an error is issued. + \note If the aggregate contains an actor with an invalid constraint, in checked builds the call is ignored and an error is issued. + + \note If the aggregate already contains actors, those actors are added to the scene as well. + + \param[in] aggregate Aggregate to add to scene. + + @see PxAggregate, PxConstraint::isValid() + */ + virtual void addAggregate(PxAggregate& aggregate) = 0; + + /** + \brief Removes an aggregate from this scene. + + \note If the aggregate is not part of this scene (see #PxAggregate::getScene), the call is ignored and an error is issued. + + \note If the aggregate contains actors, those actors are removed from the scene as well. + + \param[in] aggregate Aggregate to remove from scene. + \param[in] wakeOnLostTouch Specifies whether touching objects from the previous frame should get woken up in the next frame. Only applies to PxArticulation and PxRigidActor types. + + @see PxAggregate + */ + virtual void removeAggregate(PxAggregate& aggregate, bool wakeOnLostTouch = true) = 0; + + /** + \brief Adds objects in the collection to this scene. + + This function adds the following types of objects to this scene: PxActor, PxAggregate, PxArticulation. + This method is typically used after deserializing the collection in order to populate the scene with deserialized objects. + + \note If the collection contains an actor with an invalid constraint, in checked builds the call is ignored and an error is issued. + + \param[in] collection Objects to add to this scene. See #PxCollection + + @see PxCollection, PxConstraint::isValid() + */ + virtual void addCollection(const PxCollection& collection) = 0; + //@} + /************************************************************************************************/ + + /** @name Contained Object Retrieval + */ + //@{ + + /** + \brief Retrieve the number of actors of certain types in the scene. + + \param[in] types Combination of actor types. + \return the number of actors. + + @see getActors() + */ + virtual PxU32 getNbActors(PxActorTypeFlags types) const = 0; + + /** + \brief Retrieve an array of all the actors of certain types in the scene. + + \param[in] types Combination of actor types to retrieve. + \param[out] userBuffer The buffer to receive actor pointers. + \param[in] bufferSize Size of provided user buffer. + \param[in] startIndex Index of first actor pointer to be retrieved + \return Number of actors written to the buffer. + + @see getNbActors() + */ + virtual PxU32 getActors(PxActorTypeFlags types, PxActor** userBuffer, PxU32 bufferSize, PxU32 startIndex=0) const = 0; + + /** + \brief Queries the PxScene for a list of the PxActors whose transforms have been + updated during the previous simulation step + + \note PxSceneFlag::eENABLE_ACTIVE_ACTORS must be set. + + \note Do not use this method while the simulation is running. Calls to this method while the simulation is running will be ignored and NULL will be returned. + + \param[out] nbActorsOut The number of actors returned. + + \return A pointer to the list of active PxActors generated during the last call to fetchResults(). + + @see PxActor + */ + virtual PxActor** getActiveActors(PxU32& nbActorsOut) = 0; + + /** + \brief Returns the number of articulations in the scene. + + \return the number of articulations in this scene. + + @see getArticulations() + */ + virtual PxU32 getNbArticulations() const = 0; + + /** + \brief Retrieve all the articulations in the scene. + + \param[out] userBuffer The buffer to receive articulations pointers. + \param[in] bufferSize Size of provided user buffer. + \param[in] startIndex Index of first articulations pointer to be retrieved + \return Number of articulations written to the buffer. + + @see getNbArticulations() + */ + virtual PxU32 getArticulations(PxArticulationBase** userBuffer, PxU32 bufferSize, PxU32 startIndex=0) const = 0; + + /** + \brief Returns the number of constraint shaders in the scene. + + \return the number of constraint shaders in this scene. + + @see getConstraints() + */ + virtual PxU32 getNbConstraints() const = 0; + + /** + \brief Retrieve all the constraint shaders in the scene. + + \param[out] userBuffer The buffer to receive constraint shader pointers. + \param[in] bufferSize Size of provided user buffer. + \param[in] startIndex Index of first constraint pointer to be retrieved + \return Number of constraint shaders written to the buffer. + + @see getNbConstraints() + */ + virtual PxU32 getConstraints(PxConstraint** userBuffer, PxU32 bufferSize, PxU32 startIndex=0) const = 0; + + + /** + \brief Returns the number of aggregates in the scene. + + \return the number of aggregates in this scene. + + @see getAggregates() + */ + virtual PxU32 getNbAggregates() const = 0; + + /** + \brief Retrieve all the aggregates in the scene. + + \param[out] userBuffer The buffer to receive aggregates pointers. + \param[in] bufferSize Size of provided user buffer. + \param[in] startIndex Index of first aggregate pointer to be retrieved + \return Number of aggregates written to the buffer. + + @see getNbAggregates() + */ + virtual PxU32 getAggregates(PxAggregate** userBuffer, PxU32 bufferSize, PxU32 startIndex=0) const = 0; + + //@} + /************************************************************************************************/ + + /** @name Dominance + */ + //@{ + + /** + \brief Specifies the dominance behavior of contacts between two actors with two certain dominance groups. + + It is possible to assign each actor to a dominance groups using #PxActor::setDominanceGroup(). + + With dominance groups one can have all contacts created between actors act in one direction only. This is useful, for example, if you + want an object to push debris out of its way and be unaffected,while still responding physically to forces and collisions + with non-debris objects. + + Whenever a contact between two actors (a0, a1) needs to be solved, the groups (g0, g1) of both + actors are retrieved. Then the PxDominanceGroupPair setting for this group pair is retrieved with getDominanceGroupPair(g0, g1). + + In the contact, PxDominanceGroupPair::dominance0 becomes the dominance setting for a0, and + PxDominanceGroupPair::dominance1 becomes the dominance setting for a1. A dominanceN setting of 1.0f, the default, + will permit aN to be pushed or pulled by a(1-N) through the contact. A dominanceN setting of 0.0f, will however + prevent aN to be pushed by a(1-N) via the contact. Thus, a PxDominanceGroupPair of (1.0f, 0.0f) makes + the interaction one-way. + + + The matrix sampled by getDominanceGroupPair(g1, g2) is initialised by default such that: + + if g1 == g2, then (1.0f, 1.0f) is returned + if g1 < g2, then (0.0f, 1.0f) is returned + if g1 > g2, then (1.0f, 0.0f) is returned + + In other words, we permit actors in higher groups to be pushed around by actors in lower groups by default. + + These settings should cover most applications, and in fact not overriding these settings may likely result in higher performance. + + It is not possible to make the matrix asymetric, or to change the diagonal. In other words: + + * it is not possible to change (g1, g2) if (g1==g2) + * if you set + + (g1, g2) to X, then (g2, g1) will implicitly and automatically be set to ~X, where: + + ~(1.0f, 1.0f) is (1.0f, 1.0f) + ~(0.0f, 1.0f) is (1.0f, 0.0f) + ~(1.0f, 0.0f) is (0.0f, 1.0f) + + These two restrictions are to make sure that contacts between two actors will always evaluate to the same dominance + setting, regardless of the order of the actors. + + Dominance settings are currently specified as floats 0.0f or 1.0f because in the future we may permit arbitrary + fractional settings to express 'partly-one-way' interactions. + + Sleeping: Does NOT wake actors up automatically. + + @see getDominanceGroupPair() PxDominanceGroup PxDominanceGroupPair PxActor::setDominanceGroup() PxActor::getDominanceGroup() + */ + virtual void setDominanceGroupPair( + PxDominanceGroup group1, PxDominanceGroup group2, const PxDominanceGroupPair& dominance) = 0; + + /** + \brief Samples the dominance matrix. + + @see setDominanceGroupPair() PxDominanceGroup PxDominanceGroupPair PxActor::setDominanceGroup() PxActor::getDominanceGroup() + */ + virtual PxDominanceGroupPair getDominanceGroupPair(PxDominanceGroup group1, PxDominanceGroup group2) const = 0; + + //@} + /************************************************************************************************/ + + /** @name Dispatcher + */ + //@{ + + /** + \brief Return the cpu dispatcher that was set in PxSceneDesc::cpuDispatcher when creating the scene with PxPhysics::createScene + + @see PxSceneDesc::cpuDispatcher, PxPhysics::createScene + */ + virtual PxCpuDispatcher* getCpuDispatcher() const = 0; + + /** + \brief Return the CUDA context manager that was set in PxSceneDesc::cudaContextManager when creating the scene with PxPhysics::createScene + + Platform specific: Applies to PC GPU only. + + @see PxSceneDesc::cudaContextManager, PxPhysics::createScene + */ + virtual PxCudaContextManager* getCudaContextManager() const = 0; + + //@} + /************************************************************************************************/ + /** @name Multiclient + */ + //@{ + /** + \brief Reserves a new client ID. + + PX_DEFAULT_CLIENT is always available as the default clientID. + Additional clients are returned by this function. Clients cannot be released once created. + An error is reported when more than a supported number of clients (currently 128) are created. + + @see PxClientID + */ + virtual PxClientID createClient() = 0; + + //@} + + /************************************************************************************************/ + + /** @name Callbacks + */ + //@{ + + /** + \brief Sets a user notify object which receives special simulation events when they occur. + + \note Do not set the callback while the simulation is running. Calls to this method while the simulation is running will be ignored. + + \param[in] callback User notification callback. See #PxSimulationEventCallback. + + @see PxSimulationEventCallback getSimulationEventCallback + */ + virtual void setSimulationEventCallback(PxSimulationEventCallback* callback) = 0; + + /** + \brief Retrieves the simulationEventCallback pointer set with setSimulationEventCallback(). + + \return The current user notify pointer. See #PxSimulationEventCallback. + + @see PxSimulationEventCallback setSimulationEventCallback() + */ + virtual PxSimulationEventCallback* getSimulationEventCallback() const = 0; + + /** + \brief Sets a user callback object, which receives callbacks on all contacts generated for specified actors. + + \note Do not set the callback while the simulation is running. Calls to this method while the simulation is running will be ignored. + + \param[in] callback Asynchronous user contact modification callback. See #PxContactModifyCallback. + */ + virtual void setContactModifyCallback(PxContactModifyCallback* callback) = 0; + + /** + \brief Sets a user callback object, which receives callbacks on all CCD contacts generated for specified actors. + + \note Do not set the callback while the simulation is running. Calls to this method while the simulation is running will be ignored. + + \param[in] callback Asynchronous user contact modification callback. See #PxCCDContactModifyCallback. + */ + virtual void setCCDContactModifyCallback(PxCCDContactModifyCallback* callback) = 0; + + /** + \brief Retrieves the PxContactModifyCallback pointer set with setContactModifyCallback(). + + \return The current user contact modify callback pointer. See #PxContactModifyCallback. + + @see PxContactModifyCallback setContactModifyCallback() + */ + virtual PxContactModifyCallback* getContactModifyCallback() const = 0; + + /** + \brief Retrieves the PxCCDContactModifyCallback pointer set with setContactModifyCallback(). + + \return The current user contact modify callback pointer. See #PxContactModifyCallback. + + @see PxContactModifyCallback setContactModifyCallback() + */ + virtual PxCCDContactModifyCallback* getCCDContactModifyCallback() const = 0; + + /** + \brief Sets a broad-phase user callback object. + + \note Do not set the callback while the simulation is running. Calls to this method while the simulation is running will be ignored. + + \param[in] callback Asynchronous broad-phase callback. See #PxBroadPhaseCallback. + */ + virtual void setBroadPhaseCallback(PxBroadPhaseCallback* callback) = 0; + + /** + \brief Retrieves the PxBroadPhaseCallback pointer set with setBroadPhaseCallback(). + + \return The current broad-phase callback pointer. See #PxBroadPhaseCallback. + + @see PxBroadPhaseCallback setBroadPhaseCallback() + */ + virtual PxBroadPhaseCallback* getBroadPhaseCallback() const = 0; + + //@} + /************************************************************************************************/ + + /** @name Collision Filtering + */ + //@{ + + /** + \brief Sets the shared global filter data which will get passed into the filter shader. + + \note It is the user's responsibility to ensure that changing the shared global filter data does not change the filter output value for existing pairs. + If the filter output for existing pairs does change nonetheless then such a change will not take effect until the pair gets refiltered. + resetFiltering() can be used to explicitly refilter the pairs of specific objects. + + \note The provided data will get copied to internal buffers and this copy will be used for filtering calls. + + \note Do not use this method while the simulation is running. Calls to this method while the simulation is running will be ignored. + + \param[in] data The shared global filter shader data. + \param[in] dataSize Size of the shared global filter shader data (in bytes). + + @see getFilterShaderData() PxSceneDesc.filterShaderData PxSimulationFilterShader + */ + virtual void setFilterShaderData(const void* data, PxU32 dataSize) = 0; + + /** + \brief Gets the shared global filter data in use for this scene. + + \note The reference points to a copy of the original filter data specified in #PxSceneDesc.filterShaderData or provided by #setFilterShaderData(). + + \return Shared filter data for filter shader. + + @see getFilterShaderDataSize() setFilterShaderData() PxSceneDesc.filterShaderData PxSimulationFilterShader + */ + virtual const void* getFilterShaderData() const = 0; + + /** + \brief Gets the size of the shared global filter data (#PxSceneDesc.filterShaderData) + + \return Size of shared filter data [bytes]. + + @see getFilterShaderData() PxSceneDesc.filterShaderDataSize PxSimulationFilterShader + */ + virtual PxU32 getFilterShaderDataSize() const = 0; + + /** + \brief Gets the custom collision filter shader in use for this scene. + + \return Filter shader class that defines the collision pair filtering. + + @see PxSceneDesc.filterShader PxSimulationFilterShader + */ + virtual PxSimulationFilterShader getFilterShader() const = 0; + + /** + \brief Gets the custom collision filter callback in use for this scene. + + \return Filter callback class that defines the collision pair filtering. + + @see PxSceneDesc.filterCallback PxSimulationFilterCallback + */ + virtual PxSimulationFilterCallback* getFilterCallback() const = 0; + + /** + \brief Marks the object to reset interactions and re-run collision filters in the next simulation step. + + This call forces the object to remove all existing collision interactions, to search anew for existing contact + pairs and to run the collision filters again for found collision pairs. + + \note The operation is supported for PxRigidActor objects only. + + \note All persistent state of existing interactions will be lost and can not be retrieved even if the same collison pair + is found again in the next step. This will mean, for example, that you will not get notified about persistent contact + for such an interaction (see #PxPairFlag::eNOTIFY_TOUCH_PERSISTS), the contact pair will be interpreted as newly found instead. + + \note Lost touch contact reports will be sent for every collision pair which includes this shape, if they have + been requested through #PxPairFlag::eNOTIFY_TOUCH_LOST or #PxPairFlag::eNOTIFY_THRESHOLD_FORCE_LOST. + + \note This is an expensive operation, don't use it if you don't have to. + + \note Can be used to retrieve collision pairs that were killed by the collision filters (see #PxFilterFlag::eKILL) + + \note It is invalid to use this method if the actor has not been added to a scene already. + + \note It is invalid to use this method if PxActorFlag::eDISABLE_SIMULATION is set. + + Sleeping: Does wake up the actor. + + \param[in] actor The actor for which to re-evaluate interactions. + + @see PxSimulationFilterShader PxSimulationFilterCallback + */ + virtual void resetFiltering(PxActor& actor) = 0; + + /** + \brief Marks the object to reset interactions and re-run collision filters for specified shapes in the next simulation step. + + This is a specialization of the resetFiltering(PxActor& actor) method and allows to reset interactions for specific shapes of + a PxRigidActor. + + Sleeping: Does wake up the actor. + + \param[in] actor The actor for which to re-evaluate interactions. + \param[in] shapes The shapes for which to re-evaluate interactions. + \param[in] shapeCount Number of shapes in the list. + + @see PxSimulationFilterShader PxSimulationFilterCallback + */ + virtual void resetFiltering(PxRigidActor& actor, PxShape*const* shapes, PxU32 shapeCount) = 0; + + /** + \brief Gets the pair filtering mode for kinematic-kinematic pairs. + + \return Filtering mode for kinematic-kinematic pairs. + + @see PxPairFilteringMode PxSceneDesc + */ + virtual PxPairFilteringMode::Enum getKinematicKinematicFilteringMode() const = 0; + + /** + \brief Gets the pair filtering mode for static-kinematic pairs. + + \return Filtering mode for static-kinematic pairs. + + @see PxPairFilteringMode PxSceneDesc + */ + virtual PxPairFilteringMode::Enum getStaticKinematicFilteringMode() const = 0; + + //@} + /************************************************************************************************/ + + /** @name Simulation + */ + //@{ + /** + \brief Advances the simulation by an elapsedTime time. + + \note Large elapsedTime values can lead to instabilities. In such cases elapsedTime + should be subdivided into smaller time intervals and simulate() should be called + multiple times for each interval. + + Calls to simulate() should pair with calls to fetchResults(): + Each fetchResults() invocation corresponds to exactly one simulate() + invocation; calling simulate() twice without an intervening fetchResults() + or fetchResults() twice without an intervening simulate() causes an error + condition. + + scene->simulate(); + ...do some processing until physics is computed... + scene->fetchResults(); + ...now results of run may be retrieved. + + + \param[in] elapsedTime Amount of time to advance simulation by. The parameter has to be larger than 0, else the resulting behavior will be undefined. Range: (0, PX_MAX_F32) + \param[in] completionTask if non-NULL, this task will have its refcount incremented in simulate(), then + decremented when the scene is ready to have fetchResults called. So the task will not run until the + application also calls removeReference(). + \param[in] scratchMemBlock a memory region for physx to use for temporary data during simulation. This block may be reused by the application + after fetchResults returns. Must be aligned on a 16-byte boundary + \param[in] scratchMemBlockSize the size of the scratch memory block. Must be a multiple of 16K. + \param[in] controlSimulation if true, the scene controls its PxTaskManager simulation state. Leave + true unless the application is calling the PxTaskManager start/stopSimulation() methods itself. + + @see fetchResults() checkResults() + */ + virtual void simulate(PxReal elapsedTime, physx::PxBaseTask* completionTask = NULL, + void* scratchMemBlock = 0, PxU32 scratchMemBlockSize = 0, bool controlSimulation = true) = 0; + + + /** + \brief Performs dynamics phase of the simulation pipeline. + + \note Calls to advance() should follow calls to fetchCollision(). An error message will be issued if this sequence is not followed. + + \param[in] completionTask if non-NULL, this task will have its refcount incremented in advance(), then + decremented when the scene is ready to have fetchResults called. So the task will not run until the + application also calls removeReference(). + + */ + virtual void advance(physx::PxBaseTask* completionTask = 0) = 0; + + /** + \brief Performs collision detection for the scene over elapsedTime + + \note Calls to collide() should be the first method called to simulate a frame. + + + \param[in] elapsedTime Amount of time to advance simulation by. The parameter has to be larger than 0, else the resulting behavior will be undefined. Range: (0, PX_MAX_F32) + \param[in] completionTask if non-NULL, this task will have its refcount incremented in collide(), then + decremented when the scene is ready to have fetchResults called. So the task will not run until the + application also calls removeReference(). + \param[in] scratchMemBlock a memory region for physx to use for temporary data during simulation. This block may be reused by the application + after fetchResults returns. Must be aligned on a 16-byte boundary + \param[in] scratchMemBlockSize the size of the scratch memory block. Must be a multiple of 16K. + \param[in] controlSimulation if true, the scene controls its PxTaskManager simulation state. Leave + true unless the application is calling the PxTaskManager start/stopSimulation() methods itself. + + */ + virtual void collide(PxReal elapsedTime, physx::PxBaseTask* completionTask = 0, void* scratchMemBlock = 0, + PxU32 scratchMemBlockSize = 0, bool controlSimulation = true) = 0; + + /** + \brief This checks to see if the simulation run has completed. + + This does not cause the data available for reading to be updated with the results of the simulation, it is simply a status check. + The bool will allow it to either return immediately or block waiting for the condition to be met so that it can return true + + \param[in] block When set to true will block until the condition is met. + \return True if the results are available. + + @see simulate() fetchResults() + */ + virtual bool checkResults(bool block = false) = 0; + + /** + This method must be called after collide() and before advance(). It will wait for the collision phase to finish. If the user makes an illegal simulation call, the SDK will issue an error + message. + + \param[in] block When set to true will block until the condition is met, which is collision must finish running. + */ + + virtual bool fetchCollision(bool block = false) = 0; + + /** + This is the big brother to checkResults() it basically does the following: + + \code + if ( checkResults(block) ) + { + fire appropriate callbacks + swap buffers + return true + } + else + return false + + \endcode + + \param[in] block When set to true will block until results are available. + \param[out] errorState Used to retrieve hardware error codes. A non zero value indicates an error. + \return True if the results have been fetched. + + @see simulate() checkResults() + */ + virtual bool fetchResults(bool block = false, PxU32* errorState = 0) = 0; + + + /** + This call performs the first section of fetchResults (callbacks fired before swapBuffers), and returns a pointer to a + to the contact streams output by the simulation. It can be used to process contact pairs in parallel, which is often a limiting factor + for fetchResults() performance. + + After calling this function and processing the contact streams, call fetchResultsFinish(). Note that writes to the simulation are not + permitted between the start of fetchResultsStart() and the end of fetchResultsFinish(). + + \param[in] block When set to true will block until results are available. + \param[out] contactPairs an array of pointers to contact pair headers + \param[out] nbContactPairs the number of contact pairs + \return True if the results have been fetched. + + @see simulate() checkResults() fetchResults() fetchResultsFinish() + */ + virtual bool fetchResultsStart(const PxContactPairHeader*& contactPairs, PxU32& nbContactPairs, bool block = false) = 0; + + + /** + This call processes all event callbacks in parallel. It takes a continuation task, which will be executed once all callbacks have been processed. + + This is a utility function to make it easier to process callbacks in parallel using the PhysX task system. It can only be used in conjunction with + fetchResultsStart(...) and fetchResultsFinish(...) + + \param[in] continuation The task that will be executed once all callbacks have been processed. + */ + virtual void processCallbacks(physx::PxBaseTask* continuation) = 0; + + + /** + This call performs the second section of fetchResults: the buffer swap and subsequent callbacks. + + It must be called after fetchResultsStart() returns and contact reports have been processed. + + Note that once fetchResultsFinish() has been called, the contact streams returned in fetchResultsStart() will be invalid. + + \param[out] errorState Used to retrieve hardware error codes. A non zero value indicates an error. + + @see simulate() checkResults() fetchResults() fetchResultsStart() + */ + virtual void fetchResultsFinish(PxU32* errorState = 0) = 0; + + + /** + \brief Clear internal buffers and free memory. + + This method can be used to clear buffers and free internal memory without having to destroy the scene. Can be useful if + the physics data gets streamed in and a checkpoint with a clean state should be created. + + \note It is not allowed to call this method while the simulation is running. The call will fail. + + \param[in] sendPendingReports When set to true pending reports will be sent out before the buffers get cleaned up (for instance lost touch contact/trigger reports due to deleted objects). + */ + virtual void flushSimulation(bool sendPendingReports = false) = 0; + + /** + \brief Sets a constant gravity for the entire scene. + + Sleeping: Does NOT wake the actor up automatically. + + \param[in] vec A new gravity vector(e.g. PxVec3(0.0f,-9.8f,0.0f) ) Range: force vector + + @see PxSceneDesc.gravity getGravity() + */ + virtual void setGravity(const PxVec3& vec) = 0; + + /** + \brief Retrieves the current gravity setting. + + \return The current gravity for the scene. + + @see setGravity() PxSceneDesc.gravity + */ + virtual PxVec3 getGravity() const = 0; + + /** + \brief Set the bounce threshold velocity. Collision speeds below this threshold will not cause a bounce. + + @see PxSceneDesc::bounceThresholdVelocity, getBounceThresholdVelocity + */ + virtual void setBounceThresholdVelocity(const PxReal t) = 0; + + /** + \brief Return the bounce threshold velocity. + + @see PxSceneDesc.bounceThresholdVelocity, setBounceThresholdVelocity + */ + virtual PxReal getBounceThresholdVelocity() const = 0; + + + /** + \brief Sets the maximum number of CCD passes + + \param[in] ccdMaxPasses Maximum number of CCD passes + + @see PxSceneDesc.ccdMaxPasses getCCDMaxPasses() + + */ + virtual void setCCDMaxPasses(PxU32 ccdMaxPasses) = 0; + + /** + \brief Gets the maximum number of CCD passes. + + \return The maximum number of CCD passes. + + @see PxSceneDesc::ccdMaxPasses setCCDMaxPasses() + + */ + virtual PxU32 getCCDMaxPasses() const = 0; + + /** + \brief Return the value of frictionOffsetThreshold that was set in PxSceneDesc when creating the scene with PxPhysics::createScene + + @see PxSceneDesc::frictionOffsetThreshold, PxPhysics::createScene + */ + virtual PxReal getFrictionOffsetThreshold() const = 0; + + /** + \brief Set the friction model. + @see PxFrictionType, PxSceneDesc::frictionType + */ + virtual void setFrictionType(PxFrictionType::Enum frictionType) = 0; + + /** + \brief Return the friction model. + @see PxFrictionType, PxSceneDesc::frictionType + */ + virtual PxFrictionType::Enum getFrictionType() const = 0; + + //@} + /************************************************************************************************/ + + /** @name Visualization and Statistics + */ + //@{ + /** + \brief Function that lets you set debug visualization parameters. + + Returns false if the value passed is out of range for usage specified by the enum. + + \param[in] param Parameter to set. See #PxVisualizationParameter + \param[in] value The value to set, see #PxVisualizationParameter for allowable values. Setting to zero disables visualization for the specified property, setting to a positive value usually enables visualization and defines the scale factor. + \return False if the parameter is out of range. + + @see getVisualizationParameter PxVisualizationParameter getRenderBuffer() + */ + virtual bool setVisualizationParameter(PxVisualizationParameter::Enum param, PxReal value) = 0; + + /** + \brief Function that lets you query debug visualization parameters. + + \param[in] paramEnum The Parameter to retrieve. + \return The value of the parameter. + + @see setVisualizationParameter PxVisualizationParameter + */ + virtual PxReal getVisualizationParameter(PxVisualizationParameter::Enum paramEnum) const = 0; + + + /** + \brief Defines a box in world space to which visualization geometry will be (conservatively) culled. Use a non-empty culling box to enable the feature, and an empty culling box to disable it. + + \param[in] box the box to which the geometry will be culled. Empty box to disable the feature. + @see setVisualizationParameter getVisualizationCullingBox getRenderBuffer() + */ + virtual void setVisualizationCullingBox(const PxBounds3& box) = 0; + + /** + \brief Retrieves the visualization culling box. + + \return the box to which the geometry will be culled. + @see setVisualizationParameter setVisualizationCullingBox + */ + virtual PxBounds3 getVisualizationCullingBox() const = 0; + + /** + \brief Retrieves the render buffer. + + This will contain the results of any active visualization for this scene. + + \note Do not use this method while the simulation is running. Calls to this method while result in undefined behaviour. + + \return The render buffer. + + @see PxRenderBuffer + */ + virtual const PxRenderBuffer& getRenderBuffer() = 0; + + /** + \brief Call this method to retrieve statistics for the current simulation step. + + \note Do not use this method while the simulation is running. Calls to this method while the simulation is running will be ignored. + + \param[out] stats Used to retrieve statistics for the current simulation step. + + @see PxSimulationStatistics + */ + virtual void getSimulationStatistics(PxSimulationStatistics& stats) const = 0; + + + //@} + /************************************************************************************************/ + + /** @name Scene Query + */ + //@{ + + /** + \brief Return the value of PxSceneDesc::staticStructure that was set when creating the scene with PxPhysics::createScene + + @see PxSceneDesc::staticStructure, PxPhysics::createScene + */ + virtual PxPruningStructureType::Enum getStaticStructure() const = 0; + + /** + \brief Return the value of PxSceneDesc::dynamicStructure that was set when creating the scene with PxPhysics::createScene + + @see PxSceneDesc::dynamicStructure, PxPhysics::createScene + */ + virtual PxPruningStructureType::Enum getDynamicStructure() const = 0; + + /** + \brief Flushes any changes to the scene query representation. + + This method updates the state of the scene query representation to match changes in the scene state. + + By default, these changes are buffered until the next query is submitted. Calling this function will not change + the results from scene queries, but can be used to ensure that a query will not perform update work in the course of + its execution. + + A thread performing updates will hold a write lock on the query structure, and thus stall other querying threads. In multithread + scenarios it can be useful to explicitly schedule the period where this lock may be held for a significant period, so that + subsequent queries issued from multiple threads will not block. + + */ + virtual void flushQueryUpdates() = 0; + + /** + \brief Creates a BatchQuery object. + + Scene queries like raycasts, overlap tests and sweeps are batched in this object and are then executed at once. See #PxBatchQuery. + + \deprecated The batched query feature has been deprecated in PhysX version 3.4 + + \param[in] desc The descriptor of scene query. Scene Queries need to register a callback. See #PxBatchQueryDesc. + + @see PxBatchQuery PxBatchQueryDesc + */ + PX_DEPRECATED virtual PxBatchQuery* createBatchQuery(const PxBatchQueryDesc& desc) = 0; + + /** + \brief Sets the rebuild rate of the dynamic tree pruning structures. + + \param[in] dynamicTreeRebuildRateHint Rebuild rate of the dynamic tree pruning structures. + + @see PxSceneDesc.dynamicTreeRebuildRateHint getDynamicTreeRebuildRateHint() forceDynamicTreeRebuild() + */ + virtual void setDynamicTreeRebuildRateHint(PxU32 dynamicTreeRebuildRateHint) = 0; + + /** + \brief Retrieves the rebuild rate of the dynamic tree pruning structures. + + \return The rebuild rate of the dynamic tree pruning structures. + + @see PxSceneDesc.dynamicTreeRebuildRateHint setDynamicTreeRebuildRateHint() forceDynamicTreeRebuild() + */ + virtual PxU32 getDynamicTreeRebuildRateHint() const = 0; + + /** + \brief Forces dynamic trees to be immediately rebuilt. + + \param[in] rebuildStaticStructure True to rebuild the dynamic tree containing static objects + \param[in] rebuildDynamicStructure True to rebuild the dynamic tree containing dynamic objects + + @see PxSceneDesc.dynamicTreeRebuildRateHint setDynamicTreeRebuildRateHint() getDynamicTreeRebuildRateHint() + */ + virtual void forceDynamicTreeRebuild(bool rebuildStaticStructure, bool rebuildDynamicStructure) = 0; + + /** + \brief Sets scene query update mode + + \param[in] updateMode Scene query update mode. + + @see PxSceneQueryUpdateMode::Enum + */ + virtual void setSceneQueryUpdateMode(PxSceneQueryUpdateMode::Enum updateMode) = 0; + + /** + \brief Gets scene query update mode + + \return Current scene query update mode. + + @see PxSceneQueryUpdateMode::Enum + */ + virtual PxSceneQueryUpdateMode::Enum getSceneQueryUpdateMode() const = 0; + + /** + \brief Executes scene queries update tasks. + This function will refit dirty shapes within the pruner and will execute a task to build a new AABB tree, which is + build on a different thread. The new AABB tree is built based on the dynamic tree rebuild hint rate. Once + the new tree is ready it will be commited in next fetchQueries call, which must be called after. + + \note If PxSceneQueryUpdateMode::eBUILD_DISABLED_COMMIT_DISABLED is used, it is required to update the scene queries + using this function. + + \param[in] completionTask if non-NULL, this task will have its refcount incremented in sceneQueryUpdate(), then + decremented when the scene is ready to have fetchQueries called. So the task will not run until the + application also calls removeReference(). + \param[in] controlSimulation if true, the scene controls its PxTaskManager simulation state. Leave + true unless the application is calling the PxTaskManager start/stopSimulation() methods itself. + + @see PxSceneQueryUpdateMode::eBUILD_DISABLED_COMMIT_DISABLED + */ + virtual void sceneQueriesUpdate(physx::PxBaseTask* completionTask = NULL, bool controlSimulation = true) = 0; + + /** + \brief This checks to see if the scene queries update has completed. + + This does not cause the data available for reading to be updated with the results of the scene queries update, it is simply a status check. + The bool will allow it to either return immediately or block waiting for the condition to be met so that it can return true + + \param[in] block When set to true will block until the condition is met. + \return True if the results are available. + + @see sceneQueriesUpdate() fetchResults() + */ + virtual bool checkQueries(bool block = false) = 0; + + /** + This method must be called after sceneQueriesUpdate. It will wait for the scene queries update to finish. If the user makes an illegal scene queries update call, + the SDK will issue an error message. + + If a new AABB tree build finished, then during fetchQueries the current tree within the pruning structure is swapped with the new tree. + + \param[in] block When set to true will block until the condition is met, which is tree built task must finish running. + */ + + virtual bool fetchQueries(bool block = false) = 0; + + /** + \brief Performs a raycast against objects in the scene, returns results in a PxRaycastBuffer object + or via a custom user callback implementation inheriting from PxRaycastCallback. + + \note Touching hits are not ordered. + \note Shooting a ray from within an object leads to different results depending on the shape type. Please check the details in user guide article SceneQuery. User can ignore such objects by employing one of the provided filter mechanisms. + + \param[in] origin Origin of the ray. + \param[in] unitDir Normalized direction of the ray. + \param[in] distance Length of the ray. Has to be in the [0, inf) range. + \param[out] hitCall Raycast hit buffer or callback object used to report raycast hits. + \param[in] hitFlags Specifies which properties per hit should be computed and returned via the hit callback. + \param[in] filterData Filtering data passed to the filter shader. See #PxQueryFilterData #PxBatchQueryPreFilterShader, #PxBatchQueryPostFilterShader + \param[in] filterCall Custom filtering logic (optional). Only used if the corresponding #PxQueryFlag flags are set. If NULL, all hits are assumed to be blocking. + \param[in] cache Cached hit shape (optional). Ray is tested against cached shape first. If no hit is found the ray gets queried against the scene. + Note: Filtering is not executed for a cached shape if supplied; instead, if a hit is found, it is assumed to be a blocking hit. + Note: Using past touching hits as cache will produce incorrect behavior since the cached hit will always be treated as blocking. + + \return True if any touching or blocking hits were found or any hit was found in case PxQueryFlag::eANY_HIT was specified. + + @see PxRaycastCallback PxRaycastBuffer PxQueryFilterData PxQueryFilterCallback PxQueryCache PxRaycastHit PxQueryFlag PxQueryFlag::eANY_HIT + */ + virtual bool raycast( + const PxVec3& origin, const PxVec3& unitDir, const PxReal distance, + PxRaycastCallback& hitCall, PxHitFlags hitFlags = PxHitFlags(PxHitFlag::eDEFAULT), + const PxQueryFilterData& filterData = PxQueryFilterData(), PxQueryFilterCallback* filterCall = NULL, + const PxQueryCache* cache = NULL) const = 0; + + /** + \brief Performs a sweep test against objects in the scene, returns results in a PxSweepBuffer object + or via a custom user callback implementation inheriting from PxSweepCallback. + + \note Touching hits are not ordered. + \note If a shape from the scene is already overlapping with the query shape in its starting position, + the hit is returned unless eASSUME_NO_INITIAL_OVERLAP was specified. + + \param[in] geometry Geometry of object to sweep (supported types are: box, sphere, capsule, convex). + \param[in] pose Pose of the sweep object. + \param[in] unitDir Normalized direction of the sweep. + \param[in] distance Sweep distance. Needs to be in [0, inf) range and >0 if eASSUME_NO_INITIAL_OVERLAP was specified. Will be clamped to PX_MAX_SWEEP_DISTANCE. + \param[out] hitCall Sweep hit buffer or callback object used to report sweep hits. + \param[in] hitFlags Specifies which properties per hit should be computed and returned via the hit callback. + \param[in] filterData Filtering data and simple logic. + \param[in] filterCall Custom filtering logic (optional). Only used if the corresponding #PxQueryFlag flags are set. If NULL, all hits are assumed to be blocking. + \param[in] cache Cached hit shape (optional). Sweep is performed against cached shape first. If no hit is found the sweep gets queried against the scene. + Note: Filtering is not executed for a cached shape if supplied; instead, if a hit is found, it is assumed to be a blocking hit. + Note: Using past touching hits as cache will produce incorrect behavior since the cached hit will always be treated as blocking. + \param[in] inflation This parameter creates a skin around the swept geometry which increases its extents for sweeping. The sweep will register a hit as soon as the skin touches a shape, and will return the corresponding distance and normal. + Note: ePRECISE_SWEEP doesn't support inflation. Therefore the sweep will be performed with zero inflation. + + \return True if any touching or blocking hits were found or any hit was found in case PxQueryFlag::eANY_HIT was specified. + + + @see PxSweepCallback PxSweepBuffer PxQueryFilterData PxQueryFilterCallback PxSweepHit PxQueryCache + */ + virtual bool sweep(const PxGeometry& geometry, const PxTransform& pose, const PxVec3& unitDir, const PxReal distance, + PxSweepCallback& hitCall, PxHitFlags hitFlags = PxHitFlags(PxHitFlag::eDEFAULT), + const PxQueryFilterData& filterData = PxQueryFilterData(), PxQueryFilterCallback* filterCall = NULL, + const PxQueryCache* cache = NULL, const PxReal inflation = 0.f) const = 0; + + + /** + \brief Performs an overlap test of a given geometry against objects in the scene, returns results in a PxOverlapBuffer object + or via a custom user callback implementation inheriting from PxOverlapCallback. + + \note Filtering: returning eBLOCK from user filter for overlap queries will cause a warning (see #PxQueryHitType). + + \param[in] geometry Geometry of object to check for overlap (supported types are: box, sphere, capsule, convex). + \param[in] pose Pose of the object. + \param[out] hitCall Overlap hit buffer or callback object used to report overlap hits. + \param[in] filterData Filtering data and simple logic. See #PxQueryFilterData #PxQueryFilterCallback + \param[in] filterCall Custom filtering logic (optional). Only used if the corresponding #PxQueryFlag flags are set. If NULL, all hits are assumed to overlap. + + \return True if any touching or blocking hits were found or any hit was found in case PxQueryFlag::eANY_HIT was specified. + + \note eBLOCK should not be returned from user filters for overlap(). Doing so will result in undefined behavior, and a warning will be issued. + \note If the PxQueryFlag::eNO_BLOCK flag is set, the eBLOCK will instead be automatically converted to an eTOUCH and the warning suppressed. + + @see PxOverlapCallback PxOverlapBuffer PxHitFlags PxQueryFilterData PxQueryFilterCallback + */ + virtual bool overlap(const PxGeometry& geometry, const PxTransform& pose, PxOverlapCallback& hitCall, + const PxQueryFilterData& filterData = PxQueryFilterData(), PxQueryFilterCallback* filterCall = NULL + ) const = 0; + + + /** + \brief Retrieves the scene's internal scene query timestamp, increased each time a change to the + static scene query structure is performed. + + \return scene query static timestamp + */ + virtual PxU32 getSceneQueryStaticTimestamp() const = 0; + //@} + + /************************************************************************************************/ + /** @name Broad-phase + */ + //@{ + + /** + \brief Returns broad-phase type. + + \return Broad-phase type + */ + virtual PxBroadPhaseType::Enum getBroadPhaseType() const = 0; + + /** + \brief Gets broad-phase caps. + + \param[out] caps Broad-phase caps + \return True if success + */ + virtual bool getBroadPhaseCaps(PxBroadPhaseCaps& caps) const = 0; + + /** + \brief Returns number of regions currently registered in the broad-phase. + + \return Number of regions + */ + virtual PxU32 getNbBroadPhaseRegions() const = 0; + + /** + \brief Gets broad-phase regions. + + \param[out] userBuffer Returned broad-phase regions + \param[in] bufferSize Size of userBuffer + \param[in] startIndex Index of first desired region, in [0 ; getNbRegions()[ + \return Number of written out regions + */ + virtual PxU32 getBroadPhaseRegions(PxBroadPhaseRegionInfo* userBuffer, PxU32 bufferSize, PxU32 startIndex=0) const = 0; + + /** + \brief Adds a new broad-phase region. + + Note that by default, objects already existing in the SDK that might touch this region will not be automatically + added to the region. In other words the newly created region will be empty, and will only be populated with new + objects when they are added to the simulation, or with already existing objects when they are updated. + + It is nonetheless possible to override this default behavior and let the SDK populate the new region automatically + with already existing objects overlapping the incoming region. This has a cost though, and it should only be used + when the game can not guarantee that all objects within the new region will be added to the simulation after the + region itself. + + \param[in] region User-provided region data + \param[in] populateRegion Automatically populate new region with already existing objects overlapping it + \return Handle for newly created region, or 0xffffffff in case of failure. + */ + virtual PxU32 addBroadPhaseRegion(const PxBroadPhaseRegion& region, bool populateRegion=false) = 0; + + /** + \brief Removes a new broad-phase region. + + If the region still contains objects, and if those objects do not overlap any region any more, they are not + automatically removed from the simulation. Instead, the PxBroadPhaseCallback::onObjectOutOfBounds notification + is used for each object. Users are responsible for removing the objects from the simulation if this is the + desired behavior. + + If the handle is invalid, or if a valid handle is removed twice, an error message is sent to the error stream. + + \param[in] handle Region's handle, as returned by PxScene::addBroadPhaseRegion. + \return True if success + */ + virtual bool removeBroadPhaseRegion(PxU32 handle) = 0; + + //@} + + /************************************************************************************************/ + + /** @name Threads and Memory + */ + //@{ + + /** + \brief Get the task manager associated with this scene + + \return the task manager associated with the scene + */ + virtual PxTaskManager* getTaskManager() const = 0; + + + /** + \brief Lock the scene for reading from the calling thread. + + When the PxSceneFlag::eREQUIRE_RW_LOCK flag is enabled lockRead() must be + called before any read calls are made on the scene. + + Multiple threads may read at the same time, no threads may read while a thread is writing. + If a call to lockRead() is made while another thread is holding a write lock + then the calling thread will be blocked until the writing thread calls unlockWrite(). + + \note Lock upgrading is *not* supported, that means it is an error to + call lockRead() followed by lockWrite(). + + \note Recursive locking is supported but each lockRead() call must be paired with an unlockRead(). + + \param file String representing the calling file, for debug purposes + \param line The source file line number, for debug purposes + */ + virtual void lockRead(const char* file=NULL, PxU32 line=0) = 0; + + /** + \brief Unlock the scene from reading. + + \note Each unlockRead() must be paired with a lockRead() from the same thread. + */ + virtual void unlockRead() = 0; + + /** + \brief Lock the scene for writing from this thread. + + When the PxSceneFlag::eREQUIRE_RW_LOCK flag is enabled lockWrite() must be + called before any write calls are made on the scene. + + Only one thread may write at a time and no threads may read while a thread is writing. + If a call to lockWrite() is made and there are other threads reading then the + calling thread will be blocked until the readers complete. + + Writers have priority. If a thread is blocked waiting to write then subsequent calls to + lockRead() from other threads will be blocked until the writer completes. + + \note If multiple threads are waiting to write then the thread that is first + granted access depends on OS scheduling. + + \note Recursive locking is supported but each lockWrite() call must be paired + with an unlockWrite(). + + \note If a thread has already locked the scene for writing then it may call + lockRead(). + + \param file String representing the calling file, for debug purposes + \param line The source file line number, for debug purposes + */ + virtual void lockWrite(const char* file=NULL, PxU32 line=0) = 0; + + /** + \brief Unlock the scene from writing. + + \note Each unlockWrite() must be paired with a lockWrite() from the same thread. + */ + virtual void unlockWrite() = 0; + + + /** + \brief set the cache blocks that can be used during simulate(). + + Each frame the simulation requires memory to store contact, friction, and contact cache data. This memory is used in blocks of 16K. + Each frame the blocks used by the previous frame are freed, and may be retrieved by the application using PxScene::flushSimulation() + + This call will force allocation of cache blocks if the numBlocks parameter is greater than the currently allocated number + of blocks, and less than the max16KContactDataBlocks parameter specified at scene creation time. + + \param[in] numBlocks The number of blocks to allocate. + + @see PxSceneDesc.nbContactDataBlocks PxSceneDesc.maxNbContactDataBlocks flushSimulation() getNbContactDataBlocksUsed getMaxNbContactDataBlocksUsed + */ + virtual void setNbContactDataBlocks(PxU32 numBlocks) = 0; + + + /** + \brief get the number of cache blocks currently used by the scene + + This function may not be called while the scene is simulating + + \return the number of cache blocks currently used by the scene + + @see PxSceneDesc.nbContactDataBlocks PxSceneDesc.maxNbContactDataBlocks flushSimulation() setNbContactDataBlocks() getMaxNbContactDataBlocksUsed() + */ + virtual PxU32 getNbContactDataBlocksUsed() const = 0; + + /** + \brief get the maximum number of cache blocks used by the scene + + This function may not be called while the scene is simulating + + \return the maximum number of cache blocks everused by the scene + + @see PxSceneDesc.nbContactDataBlocks PxSceneDesc.maxNbContactDataBlocks flushSimulation() setNbContactDataBlocks() getNbContactDataBlocksUsed() + */ + virtual PxU32 getMaxNbContactDataBlocksUsed() const = 0; + + + /** + \brief Return the value of PxSceneDesc::contactReportStreamBufferSize that was set when creating the scene with PxPhysics::createScene + + @see PxSceneDesc::contactReportStreamBufferSize, PxPhysics::createScene + */ + virtual PxU32 getContactReportStreamBufferSize() const = 0; + + + /** + \brief Sets the number of actors required to spawn a separate rigid body solver thread. + + \param[in] solverBatchSize Number of actors required to spawn a separate rigid body solver thread. + + @see PxSceneDesc.solverBatchSize getSolverBatchSize() + */ + virtual void setSolverBatchSize(PxU32 solverBatchSize) = 0; + + /** + \brief Retrieves the number of actors required to spawn a separate rigid body solver thread. + + \return Current number of actors required to spawn a separate rigid body solver thread. + + @see PxSceneDesc.solverBatchSize setSolverBatchSize() + */ + virtual PxU32 getSolverBatchSize() const = 0; + + /** + \brief Sets the number of articulations required to spawn a separate rigid body solver thread. + + \param[in] solverBatchSize Number of articulations required to spawn a separate rigid body solver thread. + + @see PxSceneDesc.solverBatchSize getSolverArticulationBatchSize() + */ + virtual void setSolverArticulationBatchSize(PxU32 solverBatchSize) = 0; + + /** + \brief Retrieves the number of articulations required to spawn a separate rigid body solver thread. + + \return Current number of articulations required to spawn a separate rigid body solver thread. + + @see PxSceneDesc.solverBatchSize setSolverArticulationBatchSize() + */ + virtual PxU32 getSolverArticulationBatchSize() const = 0; + + + //@} + + /** + \brief Returns the wake counter reset value. + + \return Wake counter reset value + + @see PxSceneDesc.wakeCounterResetValue + */ + virtual PxReal getWakeCounterResetValue() const = 0; + + /** + \brief Shift the scene origin by the specified vector. + + The poses of all objects in the scene and the corresponding data structures will get adjusted to reflect the new origin location + (the shift vector will get subtracted from all object positions). + + \note It is the user's responsibility to keep track of the summed total origin shift and adjust all input/output to/from PhysX accordingly. + + \note Do not use this method while the simulation is running. Calls to this method while the simulation is running will be ignored. + + \note Make sure to propagate the origin shift to other dependent modules (for example, the character controller module etc.). + + \note This is an expensive operation and we recommend to use it only in the case where distance related precision issues may arise in areas far from the origin. + + \param[in] shift Translation vector to shift the origin by. + */ + virtual void shiftOrigin(const PxVec3& shift) = 0; + + /** + \brief Returns the Pvd client associated with the scene. + \return the client, NULL if no PVD supported. + */ + virtual PxPvdSceneClient* getScenePvdClient() = 0; + + void* userData; //!< user can assign this to whatever, usually to create a 1:1 relationship with a user object. +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/PxSceneDesc.h b/sources/PhysX/PhysX/include/PxSceneDesc.h new file mode 100644 index 00000000..f4dc1ed4 --- /dev/null +++ b/sources/PhysX/PhysX/include/PxSceneDesc.h @@ -0,0 +1,1077 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX_SCENEDESC +#define PX_PHYSICS_NX_SCENEDESC +/** \addtogroup physics +@{ +*/ + +#include "PxPhysXConfig.h" +#include "foundation/PxFlags.h" +#include "foundation/PxBounds3.h" +#include "PxFiltering.h" +#include "PxBroadPhase.h" +#include "common/PxTolerancesScale.h" +#include "task/PxTask.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + + class PxCudaContextManager; + +/** +\brief Pruning structure used to accelerate scene queries. + +eNONE uses a simple data structure that consumes less memory than the alternatives, +but generally has slower query performance. + +eDYNAMIC_AABB_TREE usually provides the fastest queries. However there is a +constant per-frame management cost associated with this structure. How much work should +be done per frame can be tuned via the #PxSceneDesc::dynamicTreeRebuildRateHint +parameter. + +eSTATIC_AABB_TREE is typically used for static objects. It is the same as the +dynamic AABB tree, without the per-frame overhead. This can be a good choice for static +objects, if no static objects are added, moved or removed after the scene has been +created. If there is no such guarantee (e.g. when streaming parts of the world in and out), +then the dynamic version is a better choice even for static objects. + +*/ +struct PxPruningStructureType +{ + enum Enum + { + eNONE, //!< Using a simple data structure + eDYNAMIC_AABB_TREE, //!< Using a dynamic AABB tree + eSTATIC_AABB_TREE, //!< Using a static AABB tree + + eLAST + }; +}; + +/** +\brief Scene query update mode + +When PxScene::fetchResults is called it does scene query related work, with this enum it is possible to +set what work is done during the fetchResults. + +FetchResults will sync changed bounds during simulation and update the scene query bounds in pruners, this work is mandatory. + +eCOMMIT_ENABLED_BUILD_ENABLED does allow to execute the new AABB tree build step during fetchResults, additionally the pruner commit is +called where any changes are applied. During commit PhysX refits the dynamic scene query tree and if a new tree was built and +the build finished the tree is swapped with current AABB tree. + +eCOMMIT_DISABLED_BUILD_ENABLED does allow to execute the new AABB tree build step during fetchResults. Pruner commit is not called, +this means that refit will then occur during the first scene query following fetchResults, or may be forced by the method PxScene::flushSceneQueryUpdates(). + +eCOMMIT_DISABLED_BUILD_DISABLED no further scene query work is executed. The scene queries update needs to be called manually, see PxScene::sceneQueriesUpdate. +It is recommended to call PxScene::sceneQueriesUpdate right after fetchResults as the pruning structures are not updated. + +*/ +struct PxSceneQueryUpdateMode +{ + enum Enum + { + eBUILD_ENABLED_COMMIT_ENABLED, //!< Both scene query build and commit are executed. + eBUILD_ENABLED_COMMIT_DISABLED, //!< Scene query build only is executed. + eBUILD_DISABLED_COMMIT_DISABLED //!< No work is done, no update of scene queries + }; +}; + + +/** +\brief Enum for selecting the friction algorithm used for simulation. + +#PxFrictionType::ePATCH selects the patch friction model which typically leads to the most stable results at low solver iteration counts and is also quite inexpensive, as it uses only +up to four scalar solver constraints per pair of touching objects. The patch friction model is the same basic strong friction algorithm as PhysX 3.2 and before. + +#PxFrictionType::eONE_DIRECTIONAL is a simplification of the Coulomb friction model, in which the friction for a given point of contact is applied in the alternating tangent directions of +the contact's normal. This simplification allows us to reduce the number of iterations required for convergence but is not as accurate as the two directional model. + +#PxFrictionType::eTWO_DIRECTIONAL is identical to the one directional model, but it applies friction in both tangent directions simultaneously. This hurts convergence a bit so it +requires more solver iterations, but is more accurate. Like the one directional model, it is applied at every contact point, which makes it potentially more expensive +than patch friction for scenarios with many contact points. + +#PxFrictionType::eFRICTION_COUNT is the total numer of friction models supported by the SDK. +*/ +struct PxFrictionType +{ + enum Enum + { + ePATCH, //!< Select default patch-friction model. + eONE_DIRECTIONAL, //!< Select one directional per-contact friction model. + eTWO_DIRECTIONAL, //!< Select two directional per-contact friction model. + eFRICTION_COUNT //!< The total number of friction models supported by the SDK. + }; +}; + + +/** +\brief Enum for selecting the type of solver used for the simulation. + +#PxSolverType::ePGS selects the default iterative sequential impulse solver. This is the same kind of solver used in PhysX 3.4 and earlier releases. + +#PxSolverType::eTGS selects a non linear iterative solver. This kind of solver can lead to improved convergence and handle large mass ratios, long chains and jointed systems better. It is slightly more expensive than the default solver and can introduce more energy to correct joint and contact errors. +*/ +struct PxSolverType +{ + enum Enum + { + ePGS, //!< Default Projected Gauss-Seidel iterative solver + eTGS //!< Temporal Gauss-Seidel solver + }; +}; + + +/** +\brief flags for configuring properties of the scene + +@see PxScene +*/ + +struct PxSceneFlag +{ + enum Enum + { + /** + \brief Enable Active Actors Notification. + + This flag enables the Active Actor Notification feature for a scene. This + feature defaults to disabled. When disabled, the function + PxScene::getActiveActors() will always return a NULL list. + + \note There may be a performance penalty for enabling the Active Actor Notification, hence this flag should + only be enabled if the application intends to use the feature. + + Default: False + */ + eENABLE_ACTIVE_ACTORS = (1<<0), + + /** + \brief Enables a second broad phase check after integration that makes it possible to prevent objects from tunneling through eachother. + + PxPairFlag::eDETECT_CCD_CONTACT requires this flag to be specified. + + \note For this feature to be effective for bodies that can move at a significant velocity, the user should raise the flag PxRigidBodyFlag::eENABLE_CCD for them. + \note This flag is not mutable, and must be set in PxSceneDesc at scene creation. + + Default: False + + @see PxRigidBodyFlag::eENABLE_CCD, PxPairFlag::eDETECT_CCD_CONTACT, eDISABLE_CCD_RESWEEP + */ + eENABLE_CCD = (1<<1), + + /** + \brief Enables a simplified swept integration strategy, which sacrifices some accuracy for improved performance. + + This simplified swept integration approach makes certain assumptions about the motion of objects that are not made when using a full swept integration. + These assumptions usually hold but there are cases where they could result in incorrect behavior between a set of fast-moving rigid bodies. A key issue is that + fast-moving dynamic objects may tunnel through each-other after a rebound. This will not happen if this mode is disabled. However, this approach will be potentially + faster than a full swept integration because it will perform significantly fewer sweeps in non-trivial scenes involving many fast-moving objects. This approach + should successfully resist objects passing through the static environment. + + PxPairFlag::eDETECT_CCD_CONTACT requires this flag to be specified. + + \note This scene flag requires eENABLE_CCD to be enabled as well. If it is not, this scene flag will do nothing. + \note For this feature to be effective for bodies that can move at a significant velocity, the user should raise the flag PxRigidBodyFlag::eENABLE_CCD for them. + \note This flag is not mutable, and must be set in PxSceneDesc at scene creation. + + Default: False + + @see PxRigidBodyFlag::eENABLE_CCD, PxPairFlag::eDETECT_CCD_CONTACT, eENABLE_CCD + */ + eDISABLE_CCD_RESWEEP = (1<<2), + + /** + \brief Enable adaptive forces to accelerate convergence of the solver. + + \note This flag is not mutable, and must be set in PxSceneDesc at scene creation. + + Default: false + */ + eADAPTIVE_FORCE = (1<<3), + + /** + \brief Enable GJK-based distance collision detection system. + + \note This flag is not mutable, and must be set in PxSceneDesc at scene creation. + + Default: true + */ + eENABLE_PCM = (1 << 6), + + /** + \brief Disable contact report buffer resize. Once the contact buffer is full, the rest of the contact reports will + not be buffered and sent. + + \note This flag is not mutable, and must be set in PxSceneDesc at scene creation. + + Default: false + */ + eDISABLE_CONTACT_REPORT_BUFFER_RESIZE = (1 << 7), + + /** + \brief Disable contact cache. + + Contact caches are used internally to provide faster contact generation. You can disable all contact caches + if memory usage for this feature becomes too high. + + \note This flag is not mutable, and must be set in PxSceneDesc at scene creation. + + Default: false + */ + eDISABLE_CONTACT_CACHE = (1 << 8), + + /** + \brief Require scene-level locking + + When set to true this requires that threads accessing the PxScene use the + multi-threaded lock methods. + + \note This flag is not mutable, and must be set in PxSceneDesc at scene creation. + + @see PxScene::lockRead + @see PxScene::unlockRead + @see PxScene::lockWrite + @see PxScene::unlockWrite + + Default: false + */ + eREQUIRE_RW_LOCK = (1 << 9), + + /** + \brief Enables additional stabilization pass in solver + + When set to true, this enables additional stabilization processing to improve that stability of complex interactions between large numbers of bodies. + + Note that this flag is not mutable and must be set in PxSceneDesc at scene creation. Also, this is an experimental feature which does result in some loss of momentum. + */ + eENABLE_STABILIZATION = (1 << 10), + + /** + \brief Enables average points in contact manifolds + + When set to true, this enables additional contacts to be generated per manifold to represent the average point in a manifold. This can stabilize stacking when only a small + number of solver iterations is used. + + Note that this flag is not mutable and must be set in PxSceneDesc at scene creation. + */ + eENABLE_AVERAGE_POINT = (1 << 11), + + /** + \brief Do not report kinematics in list of active actors. + + Since the target pose for kinematics is set by the user, an application can track the activity state directly and use + this flag to avoid that kinematics get added to the list of active actors. + + \note This flag has only an effect in combination with eENABLE_ACTIVE_ACTORS. + + @see eENABLE_ACTIVE_ACTORS + + Default: false + */ + eEXCLUDE_KINEMATICS_FROM_ACTIVE_ACTORS = (1 << 12), + + /*\brief Enables the GPU dynamics pipeline + + When set to true, a CUDA ARCH 3.0 or above-enabled NVIDIA GPU is present and the CUDA context manager has been configured, this will run the GPU dynamics pipelin instead of the CPU dynamics pipeline. + + Note that this flag is not mutable and must be set in PxSceneDesc at scene creation. + */ + eENABLE_GPU_DYNAMICS = (1 << 13), + + /** + \brief Provides improved determinism at the expense of performance. + + By default, PhysX provides limited determinism guarantees. Specifically, PhysX guarantees that the exact scene (same actors created in the same order) and simulated using the same + time-stepping scheme should provide the exact same behaviour. + + However, if additional actors are added to the simulation, this can affect the behaviour of the existing actors in the simulation, even if the set of new actors do not interact with + the existing actors. + + This flag provides an additional level of determinism that guarantees that the simulation will not change if additional actors are added to the simulation, provided those actors do not interfere + with the existing actors in the scene. Determinism is only guaranteed if the actors are inserted in a consistent order each run in a newly-created scene and simulated using a consistent time-stepping + scheme. + + Note that this flag is not mutable and must be set at scene creation. + + Note that enabling this flag can have a negative impact on performance. + + Note that this feature is not currently supported on GPU. + + Default false + */ + eENABLE_ENHANCED_DETERMINISM = (1<<14), + + /** + \brief Controls processing friction in all solver iterations + + By default, PhysX processes friction only in the final 3 position iterations, and all velocity + iterations. This flag enables friction processing in all position and velocity iterations. + + The default behaviour provides a good trade-off between performance and stability and is aimed + primarily at game development. + + When simulating more complex frictional behaviour, such as grasping of complex geometries with + a robotic manipulator, better results can be achieved by enabling friction in all solver iterations. + + \note This flag only has effect with the default solver. The TGS solver always performs friction per-iteration. + */ + eENABLE_FRICTION_EVERY_ITERATION = (1 << 15), + + eMUTABLE_FLAGS = eENABLE_ACTIVE_ACTORS|eEXCLUDE_KINEMATICS_FROM_ACTIVE_ACTORS + }; +}; + + +/** +\brief collection of set bits defined in PxSceneFlag. + +@see PxSceneFlag +*/ +typedef PxFlags PxSceneFlags; +PX_FLAGS_OPERATORS(PxSceneFlag::Enum,PxU32) + + +class PxSimulationEventCallback; +class PxContactModifyCallback; +class PxCCDContactModifyCallback; +class PxSimulationFilterCallback; + +/** +\brief Class used to retrieve limits(e.g. maximum number of bodies) for a scene. The limits +are used as a hint to the size of the scene, not as a hard limit (i.e. it will be possible +to create more objects than specified in the scene limits). + +0 indicates no limit. Using limits allows the SDK to preallocate various arrays, leading to +less re-allocations and faster code at runtime. +*/ +class PxSceneLimits +{ +public: + PxU32 maxNbActors; //!< Expected maximum number of actors + PxU32 maxNbBodies; //!< Expected maximum number of dynamic rigid bodies + PxU32 maxNbStaticShapes; //!< Expected maximum number of static shapes + PxU32 maxNbDynamicShapes; //!< Expected maximum number of dynamic shapes + PxU32 maxNbAggregates; //!< Expected maximum number of aggregates + PxU32 maxNbConstraints; //!< Expected maximum number of constraint shaders + PxU32 maxNbRegions; //!< Expected maximum number of broad-phase regions + PxU32 maxNbBroadPhaseOverlaps; //!< Expected maximum number of broad-phase overlaps + + /** + \brief constructor sets to default + */ + PX_INLINE PxSceneLimits(); + + /** + \brief (re)sets the structure to the default + */ + PX_INLINE void setToDefault(); + + /** + \brief Returns true if the descriptor is valid. + \return true if the current settings are valid. + */ + PX_INLINE bool isValid() const; +}; + +PX_INLINE PxSceneLimits::PxSceneLimits() : //constructor sets to default + maxNbActors (0), + maxNbBodies (0), + maxNbStaticShapes (0), + maxNbDynamicShapes (0), + maxNbAggregates (0), + maxNbConstraints (0), + maxNbRegions (0), + maxNbBroadPhaseOverlaps (0) +{ +} + +PX_INLINE void PxSceneLimits::setToDefault() +{ + *this = PxSceneLimits(); +} + +PX_INLINE bool PxSceneLimits::isValid() const +{ + if(maxNbRegions>256) // max number of regions is currently limited + return false; + + return true; +} + +//#if PX_SUPPORT_GPU_PHYSX +/** +\brief Sizes of pre-allocated buffers use for GPU dynamics +*/ + +struct PxgDynamicsMemoryConfig +{ + PxU32 constraintBufferCapacity; //!< Capacity of constraint buffer allocated in GPU global memory + PxU32 contactBufferCapacity; //!< Capacity of contact buffer allocated in GPU global memory + PxU32 tempBufferCapacity; //!< Capacity of temp buffer allocated in pinned host memory. + PxU32 contactStreamSize; //!< Size of contact stream buffer allocated in pinned host memory. This is double-buffered so total allocation size = 2* contactStreamCapacity * sizeof(PxContact). + PxU32 patchStreamSize; //!< Size of the contact patch stream buffer allocated in pinned host memory. This is double-buffered so total allocation size = 2 * patchStreamCapacity * sizeof(PxContactPatch). + PxU32 forceStreamCapacity; //!< Capacity of force buffer allocated in pinned host memory. + PxU32 heapCapacity; //!< Initial capacity of the GPU and pinned host memory heaps. Additional memory will be allocated if more memory is required. + PxU32 foundLostPairsCapacity; //!< Capacity of found and lost buffers allocated in GPU global memory. This is used for the found/lost pair reports in the BP. + + PxgDynamicsMemoryConfig() : + constraintBufferCapacity(32 * 1024 * 1024), + contactBufferCapacity(24 * 1024 * 1024), + tempBufferCapacity(16 * 1024 * 1024), + contactStreamSize(1024 * 512), + patchStreamSize(1024 * 80), + forceStreamCapacity(1 * 1024 * 1024), + heapCapacity(64 * 1024 * 1024), + foundLostPairsCapacity(256 * 1024) + { + } +}; + +//#endif + +/** +\brief Descriptor class for scenes. See #PxScene. + +This struct must be initialized with the same PxTolerancesScale values used to initialize PxPhysics. + +@see PxScene PxPhysics.createScene PxTolerancesScale +*/ +class PxSceneDesc +{ +public: + + /** + \brief Gravity vector. + + Range: force vector
+ Default: Zero + + @see PxScene.setGravity() + + When setting gravity, you should probably also set bounce threshold. + */ + PxVec3 gravity; + + /** + \brief Possible notification callback. + + Default: NULL + + @see PxSimulationEventCallback PxScene.setSimulationEventCallback() PxScene.getSimulationEventCallback() + */ + PxSimulationEventCallback* simulationEventCallback; + + /** + \brief Possible asynchronous callback for contact modification. + + Default: NULL + + @see PxContactModifyCallback PxScene.setContactModifyCallback() PxScene.getContactModifyCallback() + */ + PxContactModifyCallback* contactModifyCallback; + + /** + \brief Possible asynchronous callback for contact modification. + + Default: NULL + + @see PxContactModifyCallback PxScene.setContactModifyCallback() PxScene.getContactModifyCallback() + */ + PxCCDContactModifyCallback* ccdContactModifyCallback; + + /** + \brief Shared global filter data which will get passed into the filter shader. + + \note The provided data will get copied to internal buffers and this copy will be used for filtering calls. + + Default: NULL + + @see PxSimulationFilterShader PxScene::setFilterShaderData() + */ + const void* filterShaderData; + + /** + \brief Size (in bytes) of the shared global filter data #filterShaderData. + + Default: 0 + + @see PxSimulationFilterShader filterShaderData + */ + PxU32 filterShaderDataSize; + + /** + \brief The custom filter shader to use for collision filtering. + + \note This parameter is compulsory. If you don't want to define your own filter shader you can + use the default shader #PxDefaultSimulationFilterShader which can be found in the PhysX extensions + library. + + @see PxSimulationFilterShader + */ + PxSimulationFilterShader filterShader; + + /** + \brief A custom collision filter callback which can be used to implement more complex filtering operations which need + access to the simulation state, for example. + + Default: NULL + + @see PxSimulationFilterCallback + */ + PxSimulationFilterCallback* filterCallback; + + /** + \brief Filtering mode for kinematic-kinematic pairs in the broadphase. + + Default: PxPairFilteringMode::eDEFAULT + + @see PxPairFilteringMode + */ + PxPairFilteringMode::Enum kineKineFilteringMode; + + /** + \brief Filtering mode for static-kinematic pairs in the broadphase. + + Default: PxPairFilteringMode::eDEFAULT + + @see PxPairFilteringMode + */ + PxPairFilteringMode::Enum staticKineFilteringMode; + + /** + \brief Selects the broad-phase algorithm to use. + + Default: PxBroadPhaseType::eABP + + @see PxBroadPhaseType + */ + PxBroadPhaseType::Enum broadPhaseType; + + /** + \brief Broad-phase callback + + Default: NULL + + @see PxBroadPhaseCallback + */ + PxBroadPhaseCallback* broadPhaseCallback; + + /** + \brief Expected scene limits. + + @see PxSceneLimits + */ + PxSceneLimits limits; + + /** + \brief Selects the friction algorithm to use for simulation. + + \note frictionType cannot be modified after the first call to any of PxScene::simulate, PxScene::solve and PxScene::collide + + @see PxFrictionType + Default: PxFrictionType::ePATCH + + @see PxScene::setFrictionType, PxScene::getFrictionType + */ + PxFrictionType::Enum frictionType; + + /** + \brief Selects the solver algorithm to use. + + Default: PxSolverType::ePGS + + @see PxSolverType + */ + PxSolverType::Enum solverType; + + /** + \brief A contact with a relative velocity below this will not bounce. A typical value for simulation. + stability is about 0.2 * gravity. + + Range: [0, PX_MAX_F32)
+ Default: 0.2 * PxTolerancesScale::speed + + @see PxMaterial + */ + PxReal bounceThresholdVelocity; + + /** + \brief A threshold of contact separation distance used to decide if a contact point will experience friction forces. + + \note If the separation distance of a contact point is greater than the threshold then the contact point will not experience friction forces. + + \note If the aggregated contact offset of a pair of shapes is large it might be desirable to neglect friction + for contact points whose separation distance is sufficiently large that the shape surfaces are clearly separated. + + \note This parameter can be used to tune the separation distance of contact points at which friction starts to have an effect. + + Range: [0, PX_MAX_F32)
+ Default: 0.04 * PxTolerancesScale::length + */ + PxReal frictionOffsetThreshold; + + /** + \brief A threshold for speculative CCD. Used to control whether bias, restitution or a combination of the two are used to resolve the contacts. + + \note This only has any effect on contacting pairs where one of the bodies has PxRigidBodyFlag::eENABLE_SPECULATIVE_CCD raised. + + Range: [0, PX_MAX_F32)
+ Default: 0.04 * PxTolerancesScale::length + */ + + PxReal ccdMaxSeparation; + + /** + \brief A slop value used to zero contact offsets from the body's COM on an axis if the offset along that axis is smaller than this threshold. Can be used to compensate + for small numerical errors in contact generation. + + Range: [0, PX_MAX_F32)
+ Default: 0.0 + */ + + PxReal solverOffsetSlop; + + /** + \brief Flags used to select scene options. + + @see PxSceneFlag PxSceneFlags + */ + PxSceneFlags flags; + + /** + \brief The CPU task dispatcher for the scene. + + See PxCpuDispatcher, PxScene::getCpuDispatcher + */ + PxCpuDispatcher* cpuDispatcher; + + /** + \brief The CUDA context manager for the scene. + + Platform specific: Applies to PC GPU only. + + See PxCudaContextManager, PxScene::getCudaContextManager + */ + PxCudaContextManager* cudaContextManager; + + /** + \brief Defines the structure used to store static objects. + + \note Only PxPruningStructureType::eSTATIC_AABB_TREE and PxPruningStructureType::eDYNAMIC_AABB_TREE are allowed here. + */ + PxPruningStructureType::Enum staticStructure; + + /** + \brief Defines the structure used to store dynamic objects. + */ + PxPruningStructureType::Enum dynamicStructure; + + /** + \brief Hint for how much work should be done per simulation frame to rebuild the pruning structure. + + This parameter gives a hint on the distribution of the workload for rebuilding the dynamic AABB tree + pruning structure #PxPruningStructureType::eDYNAMIC_AABB_TREE. It specifies the desired number of simulation frames + the rebuild process should take. Higher values will decrease the workload per frame but the pruning + structure will get more and more outdated the longer the rebuild takes (which can make + scene queries less efficient). + + \note Only used for #PxPruningStructureType::eDYNAMIC_AABB_TREE pruning structure. + + \note This parameter gives only a hint. The rebuild process might still take more or less time depending on the + number of objects involved. + + Range: [4, PX_MAX_U32)
+ Default: 100 + */ + PxU32 dynamicTreeRebuildRateHint; + + /** + \brief Defines the scene query update mode. + Default: PxSceneQueryUpdateMode::eBUILD_ENABLED_COMMIT_ENABLED + */ + PxSceneQueryUpdateMode::Enum sceneQueryUpdateMode; + + /** + \brief Will be copied to PxScene::userData. + + Default: NULL + */ + void* userData; + + /** + \brief Defines the number of actors required to spawn a separate rigid body solver island task chain. + + This parameter defines the minimum number of actors required to spawn a separate rigid body solver task chain. Setting a low value + will potentially cause more task chains to be generated. This may result in the overhead of spawning tasks can become a limiting performance factor. + Setting a high value will potentially cause fewer islands to be generated. This may reduce thread scaling (fewer task chains spawned) and may + detrimentally affect performance if some bodies in the scene have large solver iteration counts because all constraints in a given island are solved by the + maximum number of solver iterations requested by any body in the island. + + Note that a rigid body solver task chain is spawned as soon as either a sufficient number of rigid bodies or articulations are batched together. + + Default: 128 + + @see PxScene.setSolverBatchSize() PxScene.getSolverBatchSize() + */ + PxU32 solverBatchSize; + + /** + \brief Defines the number of articulations required to spawn a separate rigid body solver island task chain. + + This parameter defines the minimum number of articulations required to spawn a separate rigid body solver task chain. Setting a low value + will potentially cause more task chains to be generated. This may result in the overhead of spawning tasks can become a limiting performance factor. + Setting a high value will potentially cause fewer islands to be generated. This may reduce thread scaling (fewer task chains spawned) and may + detrimentally affect performance if some bodies in the scene have large solver iteration counts because all constraints in a given island are solved by the + maximum number of solver iterations requested by any body in the island. + + Note that a rigid body solver task chain is spawned as soon as either a sufficient number of rigid bodies or articulations are batched together. + + Default: 128 + + @see PxScene.setSolverArticulationBatchSize() PxScene.getSolverArticulationBatchSize() + */ + PxU32 solverArticulationBatchSize; + + /** + \brief Setting to define the number of 16K blocks that will be initially reserved to store contact, friction, and contact cache data. + This is the number of 16K memory blocks that will be automatically allocated from the user allocator when the scene is instantiated. Further 16k + memory blocks may be allocated during the simulation up to maxNbContactDataBlocks. + + \note This value cannot be larger than maxNbContactDataBlocks because that defines the maximum number of 16k blocks that can be allocated by the SDK. + + Default: 0 + + Range: [0, PX_MAX_U32]
+ + @see PxPhysics::createScene PxScene::setNbContactDataBlocks + */ + PxU32 nbContactDataBlocks; + + /** + \brief Setting to define the maximum number of 16K blocks that can be allocated to store contact, friction, and contact cache data. + As the complexity of a scene increases, the SDK may require to allocate new 16k blocks in addition to the blocks it has already + allocated. This variable controls the maximum number of blocks that the SDK can allocate. + + In the case that the scene is sufficiently complex that all the permitted 16K blocks are used, contacts will be dropped and + a warning passed to the error stream. + + If a warning is reported to the error stream to indicate the number of 16K blocks is insufficient for the scene complexity + then the choices are either (i) re-tune the number of 16K data blocks until a number is found that is sufficient for the scene complexity, + (ii) to simplify the scene or (iii) to opt to not increase the memory requirements of physx and accept some dropped contacts. + + Default: 65536 + + Range: [0, PX_MAX_U32]
+ + @see nbContactDataBlocks PxScene::setNbContactDataBlocks + */ + PxU32 maxNbContactDataBlocks; + + /** + \brief The maximum bias coefficient used in the constraint solver + + When geometric errors are found in the constraint solver, either as a result of shapes penetrating + or joints becoming separated or violating limits, a bias is introduced in the solver position iterations + to correct these errors. This bias is proportional to 1/dt, meaning that the bias becomes increasingly + strong as the time-step passed to PxScene::simulate(...) becomes smaller. This coefficient allows the + application to restrict how large the bias coefficient is, to reduce how violent error corrections are. + This can improve simulation quality in cases where either variable time-steps or extremely small time-steps + are used. + + Default: PX_MAX_F32 + + Range [0, PX_MAX_F32]
+ + */ + PxReal maxBiasCoefficient; + + /** + \brief Size of the contact report stream (in bytes). + + The contact report stream buffer is used during the simulation to store all the contact reports. + If the size is not sufficient, the buffer will grow by a factor of two. + It is possible to disable the buffer growth by setting the flag PxSceneFlag::eDISABLE_CONTACT_REPORT_BUFFER_RESIZE. + In that case the buffer will not grow but contact reports not stored in the buffer will not get sent in the contact report callbacks. + + Default: 8192 + + Range: (0, PX_MAX_U32]
+ + */ + PxU32 contactReportStreamBufferSize; + + /** + \brief Maximum number of CCD passes + + The CCD performs multiple passes, where each pass every object advances to its time of first impact. This value defines how many passes the CCD system should perform. + + \note The CCD system is a multi-pass best-effort conservative advancement approach. After the defined number of passes has been completed, any remaining time is dropped. + \note This defines the maximum number of passes the CCD can perform. It may perform fewer if additional passes are not necessary. + + Default: 1 + Range: [1, PX_MAX_U32]
+ */ + PxU32 ccdMaxPasses; + + /** + \brief CCD threshold + + CCD performs sweeps against shapes if and only if the relative motion of the shapes is fast-enough that a collision would be missed + by the discrete contact generation. However, in some circumstances, e.g. when the environment is constructed from large convex shapes, this + approach may produce undesired simulation artefacts. This parameter defines the minimum relative motion that would be required to force CCD between shapes. + The smaller of this value and the sum of the thresholds calculated for the shapes involved will be used. + + \note It is not advisable to set this to a very small value as this may lead to CCD "jamming" and detrimentally effect performance. This value should be at least larger than the translation caused by a single frame's gravitational effect + + Default: PX_MAX_F32 + Range: [Eps, PX_MAX_F32]
+ */ + + PxReal ccdThreshold; + + /** + \brief The wake counter reset value + + Calling wakeUp() on objects which support sleeping will set their wake counter value to the specified reset value. + + Range: (0, PX_MAX_F32)
+ Default: 0.4 (which corresponds to 20 frames for a time step of 0.02) + + @see PxRigidDynamic::wakeUp() PxArticulationBase::wakeUp() + */ + PxReal wakeCounterResetValue; + + /** + \brief The bounds used to sanity check user-set positions of actors and articulation links + + These bounds are used to check the position values of rigid actors inserted into the scene, and positions set for rigid actors + already within the scene. + + Range: any valid PxBounds3
+ Default: (-PX_MAX_BOUNDS_EXTENTS, PX_MAX_BOUNDS_EXTENTS) on each axis + */ + PxBounds3 sanityBounds; + + /** + \brief The pre-allocations performed in the GPU dynamics pipeline. + */ + PxgDynamicsMemoryConfig gpuDynamicsConfig; + + /** + \brief Limitation for the partitions in the GPU dynamics pipeline. + This variable must be power of 2. + A value greater than 32 is currently not supported. + Range: (1, 32)
+ */ + PxU32 gpuMaxNumPartitions; + + /** + \brief Defines which compute version the GPU dynamics should target. DO NOT MODIFY + */ + PxU32 gpuComputeVersion; + +private: + /** + \cond + */ + // For internal use only + PxTolerancesScale tolerancesScale; + /** + \endcond + */ + + +public: + /** + \brief constructor sets to default. + + \param[in] scale scale values for the tolerances in the scene, these must be the same values passed into + PxCreatePhysics(). The affected tolerances are bounceThresholdVelocity and frictionOffsetThreshold. + + @see PxCreatePhysics() PxTolerancesScale bounceThresholdVelocity frictionOffsetThreshold + */ + PX_INLINE PxSceneDesc(const PxTolerancesScale& scale); + + /** + \brief (re)sets the structure to the default. + + \param[in] scale scale values for the tolerances in the scene, these must be the same values passed into + PxCreatePhysics(). The affected tolerances are bounceThresholdVelocity and frictionOffsetThreshold. + + @see PxCreatePhysics() PxTolerancesScale bounceThresholdVelocity frictionOffsetThreshold + */ + PX_INLINE void setToDefault(const PxTolerancesScale& scale); + + /** + \brief Returns true if the descriptor is valid. + \return true if the current settings are valid. + */ + PX_INLINE bool isValid() const; + + /** + \cond + */ + // For internal use only + PX_INLINE const PxTolerancesScale& getTolerancesScale() const { return tolerancesScale; } + /** + \endcond + */ +}; + +PX_INLINE PxSceneDesc::PxSceneDesc(const PxTolerancesScale& scale): + gravity (PxVec3(0.0f)), + simulationEventCallback (NULL), + contactModifyCallback (NULL), + ccdContactModifyCallback (NULL), + + filterShaderData (NULL), + filterShaderDataSize (0), + filterShader (NULL), + filterCallback (NULL), + + kineKineFilteringMode (PxPairFilteringMode::eDEFAULT), + staticKineFilteringMode (PxPairFilteringMode::eDEFAULT), + + broadPhaseType (PxBroadPhaseType::eABP), + broadPhaseCallback (NULL), + + frictionType (PxFrictionType::ePATCH), + solverType (PxSolverType::ePGS), + bounceThresholdVelocity (0.2f * scale.speed), + frictionOffsetThreshold (0.04f * scale.length), + ccdMaxSeparation (0.04f * scale.length), + solverOffsetSlop (0.0f), + + flags (PxSceneFlag::eENABLE_PCM), + + cpuDispatcher (NULL), + cudaContextManager (NULL), + + staticStructure (PxPruningStructureType::eDYNAMIC_AABB_TREE), + dynamicStructure (PxPruningStructureType::eDYNAMIC_AABB_TREE), + dynamicTreeRebuildRateHint (100), + sceneQueryUpdateMode (PxSceneQueryUpdateMode::eBUILD_ENABLED_COMMIT_ENABLED), + + userData (NULL), + + solverBatchSize (128), + solverArticulationBatchSize (16), + + nbContactDataBlocks (0), + maxNbContactDataBlocks (1<<16), + maxBiasCoefficient (PX_MAX_F32), + contactReportStreamBufferSize (8192), + ccdMaxPasses (1), + ccdThreshold (PX_MAX_F32), + wakeCounterResetValue (20.0f*0.02f), + sanityBounds (PxBounds3(PxVec3(-PX_MAX_BOUNDS_EXTENTS), PxVec3(PX_MAX_BOUNDS_EXTENTS))), + gpuMaxNumPartitions (8), + gpuComputeVersion (0), + tolerancesScale (scale) +{ +} + +PX_INLINE void PxSceneDesc::setToDefault(const PxTolerancesScale& scale) +{ + *this = PxSceneDesc(scale); +} + +PX_INLINE bool PxSceneDesc::isValid() const +{ + if(!filterShader) + return false; + + if( ((filterShaderDataSize == 0) && (filterShaderData != NULL)) || + ((filterShaderDataSize > 0) && (filterShaderData == NULL)) ) + return false; + + if(!limits.isValid()) + return false; + + if(staticStructure!=PxPruningStructureType::eSTATIC_AABB_TREE && staticStructure!=PxPruningStructureType::eDYNAMIC_AABB_TREE) + return false; + + if(dynamicTreeRebuildRateHint < 4) + return false; + + if(bounceThresholdVelocity < 0.0f) + return false; + if(frictionOffsetThreshold < 0.0f) + return false; + if(ccdMaxSeparation < 0.0f) + return false; + if (solverOffsetSlop < 0.f) + return false; + + if(ccdThreshold <= 0.f) + return false; + + if(!cpuDispatcher) + return false; + + if(!contactReportStreamBufferSize) + return false; + + if(maxNbContactDataBlocks < nbContactDataBlocks) + return false; + + if(wakeCounterResetValue <= 0.0f) + return false; + + //Adaptive force and stabilization are incompatible. You can only have one or the other + if((flags & (PxSceneFlag::eADAPTIVE_FORCE | PxSceneFlag::eENABLE_STABILIZATION)) == (PxSceneFlag::eADAPTIVE_FORCE | PxSceneFlag::eENABLE_STABILIZATION)) + return false; + + if(!sanityBounds.isValid()) + return false; + +#if PX_SUPPORT_GPU_PHYSX + //gpuMaxNumPartitions must be power of 2 + if((gpuMaxNumPartitions&(gpuMaxNumPartitions - 1)) != 0) + return false; + if (gpuMaxNumPartitions > 32) + return false; +#endif + + return true; +} + + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/PxSceneLock.h b/sources/PhysX/PhysX/include/PxSceneLock.h new file mode 100644 index 00000000..fcd8236e --- /dev/null +++ b/sources/PhysX/PhysX/include/PxSceneLock.h @@ -0,0 +1,129 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX_SCENELOCK +#define PX_PHYSICS_NX_SCENELOCK +/** \addtogroup physics +@{ +*/ + +#include "PxPhysXConfig.h" +#include "PxScene.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief RAII wrapper for the PxScene read lock. + +Use this class as follows to lock the scene for reading by the current thread +for the duration of the enclosing scope: + + PxSceneReadLock lock(sceneRef); + +\see PxScene::lockRead(), PxScene::unlockRead(), PxSceneFlag::eREQUIRE_RW_LOCK +*/ +class PxSceneReadLock +{ + PxSceneReadLock(const PxSceneReadLock&); + PxSceneReadLock& operator=(const PxSceneReadLock&); + +public: + + /** + \brief Constructor + \param scene The scene to lock for reading + \param file Optional string for debugging purposes + \param line Optional line number for debugging purposes + */ + PxSceneReadLock(PxScene& scene, const char* file=NULL, PxU32 line=0) + : mScene(scene) + { + mScene.lockRead(file, line); + } + + ~PxSceneReadLock() + { + mScene.unlockRead(); + } + +private: + + PxScene& mScene; +}; + +/** +\brief RAII wrapper for the PxScene write lock. + +Use this class as follows to lock the scene for writing by the current thread +for the duration of the enclosing scope: + + PxSceneWriteLock lock(sceneRef); + +\see PxScene::lockWrite(), PxScene::unlockWrite(), PxSceneFlag::eREQUIRE_RW_LOCK +*/ +class PxSceneWriteLock +{ + PxSceneWriteLock(const PxSceneWriteLock&); + PxSceneWriteLock& operator=(const PxSceneWriteLock&); + +public: + + /** + \brief Constructor + \param scene The scene to lock for writing + \param file Optional string for debugging purposes + \param line Optional line number for debugging purposes + */ + PxSceneWriteLock(PxScene& scene, const char* file=NULL, PxU32 line=0) + : mScene(scene) + { + mScene.lockWrite(file, line); + } + + ~PxSceneWriteLock() + { + mScene.unlockWrite(); + } + +private: + + PxScene& mScene; +}; + + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/PxShape.h b/sources/PhysX/PhysX/include/PxShape.h new file mode 100644 index 00000000..812f603c --- /dev/null +++ b/sources/PhysX/PhysX/include/PxShape.h @@ -0,0 +1,639 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_PHYSICS_NX_SHAPE +#define PX_PHYSICS_NX_SHAPE +/** \addtogroup physics +@{ +*/ + +#include "PxPhysXConfig.h" +#include "common/PxBase.h" +#include "geometry/PxGeometry.h" +#include "geometry/PxGeometryHelpers.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxBoxGeometry; +class PxSphereGeometry; +class PxCapsuleGeometry; +class PxPlaneGeometry; +class PxConvexMeshGeometry; +class PxTriangleMeshGeometry; +class PxHeightFieldGeometry; +class PxRigidActor; +struct PxFilterData; +struct PxRaycastHit; +struct PxSweepHit; + +/** +\brief Flags which affect the behavior of PxShapes. + +@see PxShape PxShape.setFlag() +*/ +struct PxShapeFlag +{ + enum Enum + { + /** + \brief The shape will partake in collision in the physical simulation. + + \note It is illegal to raise the eSIMULATION_SHAPE and eTRIGGER_SHAPE flags. + In the event that one of these flags is already raised the sdk will reject any + attempt to raise the other. To raise the eSIMULATION_SHAPE first ensure that + eTRIGGER_SHAPE is already lowered. + + \note This flag has no effect if simulation is disabled for the corresponding actor (see #PxActorFlag::eDISABLE_SIMULATION). + + @see PxSimulationEventCallback.onContact() PxScene.setSimulationEventCallback() PxShape.setFlag(), PxShape.setFlags() + */ + eSIMULATION_SHAPE = (1<<0), + + /** + \brief The shape will partake in scene queries (ray casts, overlap tests, sweeps, ...). + */ + eSCENE_QUERY_SHAPE = (1<<1), + + /** + \brief The shape is a trigger which can send reports whenever other shapes enter/leave its volume. + + \note Triangle meshes and heightfields can not be triggers. Shape creation will fail in these cases. + + \note Shapes marked as triggers do not collide with other objects. If an object should act both + as a trigger shape and a collision shape then create a rigid body with two shapes, one being a + trigger shape and the other a collision shape. It is illegal to raise the eTRIGGER_SHAPE and + eSIMULATION_SHAPE flags on a single PxShape instance. In the event that one of these flags is already + raised the sdk will reject any attempt to raise the other. To raise the eTRIGGER_SHAPE flag first + ensure that eSIMULATION_SHAPE flag is already lowered. + + \note Trigger shapes will no longer send notification events for interactions with other trigger shapes. + + \note Shapes marked as triggers are allowed to participate in scene queries, provided the eSCENE_QUERY_SHAPE flag is set. + + \note This flag has no effect if simulation is disabled for the corresponding actor (see #PxActorFlag::eDISABLE_SIMULATION). + + @see PxSimulationEventCallback.onTrigger() PxScene.setSimulationEventCallback() PxShape.setFlag(), PxShape.setFlags() + */ + eTRIGGER_SHAPE = (1<<2), + + /** + \brief Enable debug renderer for this shape + + @see PxScene.getRenderBuffer() PxRenderBuffer PxVisualizationParameter + */ + eVISUALIZATION = (1<<3) + }; +}; + +/** +\brief collection of set bits defined in PxShapeFlag. + +@see PxShapeFlag +*/ +typedef PxFlags PxShapeFlags; +PX_FLAGS_OPERATORS(PxShapeFlag::Enum,PxU8) + + +/** +\brief Abstract class for collision shapes. + +Shapes are shared, reference counted objects. + +An instance can be created by calling the createShape() method of the PxRigidActor class, or +the createShape() method of the PxPhysics class. + +

Visualizations

+\li PxVisualizationParameter::eCOLLISION_AABBS +\li PxVisualizationParameter::eCOLLISION_SHAPES +\li PxVisualizationParameter::eCOLLISION_AXES + +@see PxPhysics.createShape() PxRigidActor.createShape() PxBoxGeometry PxSphereGeometry PxCapsuleGeometry PxPlaneGeometry PxConvexMeshGeometry +PxTriangleMeshGeometry PxHeightFieldGeometry +*/ +class PxShape : public PxBase +{ +public: + + /** + \brief Decrements the reference count of a shape and releases it if the new reference count is zero. + + Note that in releases prior to PhysX 3.3 this method did not have reference counting semantics and was used to destroy a shape + created with PxActor::createShape(). In PhysX 3.3 and above, this usage is deprecated, instead, use PxRigidActor::detachShape() to detach + a shape from an actor. If the shape to be detached was created with PxActor::createShape(), the actor holds the only counted reference, + and so when the shape is detached it will also be destroyed. + + @see PxRigidActor::createShape() PxPhysics::createShape() PxRigidActor::attachShape() PxRigidActor::detachShape() + */ + virtual void release() = 0; + + /** + \brief Returns the reference count of the shape. + + At creation, the reference count of the shape is 1. Every actor referencing this shape increments the + count by 1. When the reference count reaches 0, and only then, the shape gets destroyed automatically. + + \return the current reference count. + */ + virtual PxU32 getReferenceCount() const = 0; + + /** + \brief Acquires a counted reference to a shape. + + This method increases the reference count of the shape by 1. Decrement the reference count by calling release() + */ + virtual void acquireReference() = 0; + + /** + \brief Get the geometry type of the shape. + + \return Type of shape geometry. + + @see PxGeometryType + */ + virtual PxGeometryType::Enum getGeometryType() const = 0; + + /** + \brief Adjust the geometry of the shape. + + \note The type of the passed in geometry must match the geometry type of the shape. + \note It is not allowed to change the geometry type of a shape. + \note This function does not guarantee correct/continuous behavior when objects are resting on top of old or new geometry. + + \param[in] geometry New geometry of the shape. + + @see PxGeometry PxGeometryType getGeometryType() + */ + virtual void setGeometry(const PxGeometry& geometry) = 0; + + + /** + \brief Retrieve the geometry from the shape in a PxGeometryHolder wrapper class. + + \return a PxGeometryHolder object containing the geometry; + + @see PxGeometry PxGeometryType getGeometryType() setGeometry() + */ + + virtual PxGeometryHolder getGeometry() const = 0; + + + /** + \brief Fetch the geometry of the shape. + + \note If the type of geometry to extract does not match the geometry type of the shape + then the method will return false and the passed in geometry descriptor is not modified. + + \param[in] geometry The descriptor to save the shape's geometry data to. + \return True on success else false + + @see PxGeometry PxGeometryType getGeometryType() + */ + virtual bool getBoxGeometry(PxBoxGeometry& geometry) const = 0; + + /** + \brief Fetch the geometry of the shape. + + \note If the type of geometry to extract does not match the geometry type of the shape + then the method will return false and the passed in geometry descriptor is not modified. + + \param[in] geometry The descriptor to save the shape's geometry data to. + \return True on success else false + + @see PxGeometry PxGeometryType getGeometryType() + */ + virtual bool getSphereGeometry(PxSphereGeometry& geometry) const = 0; + + /** + \brief Fetch the geometry of the shape. + + \note If the type of geometry to extract does not match the geometry type of the shape + then the method will return false and the passed in geometry descriptor is not modified. + + \param[in] geometry The descriptor to save the shape's geometry data to. + \return True on success else false + + @see PxGeometry PxGeometryType getGeometryType() + */ + virtual bool getCapsuleGeometry(PxCapsuleGeometry& geometry) const = 0; + + /** + \brief Fetch the geometry of the shape. + + \note If the type of geometry to extract does not match the geometry type of the shape + then the method will return false and the passed in geometry descriptor is not modified. + + \param[in] geometry The descriptor to save the shape's geometry data to. + \return True on success else false + + @see PxGeometry PxGeometryType getGeometryType() + */ + virtual bool getPlaneGeometry(PxPlaneGeometry& geometry) const = 0; + + /** + \brief Fetch the geometry of the shape. + + \note If the type of geometry to extract does not match the geometry type of the shape + then the method will return false and the passed in geometry descriptor is not modified. + + \param[in] geometry The descriptor to save the shape's geometry data to. + \return True on success else false + + @see PxGeometry PxGeometryType getGeometryType() + */ + virtual bool getConvexMeshGeometry(PxConvexMeshGeometry& geometry) const = 0; + + /** + \brief Fetch the geometry of the shape. + + \note If the type of geometry to extract does not match the geometry type of the shape + then the method will return false and the passed in geometry descriptor is not modified. + + \param[in] geometry The descriptor to save the shape's geometry data to. + \return True on success else false + + @see PxGeometry PxGeometryType getGeometryType() + */ + virtual bool getTriangleMeshGeometry(PxTriangleMeshGeometry& geometry) const = 0; + + + /** + \brief Fetch the geometry of the shape. + + \note If the type of geometry to extract does not match the geometry type of the shape + then the method will return false and the passed in geometry descriptor is not modified. + + \param[in] geometry The descriptor to save the shape's geometry data to. + \return True on success else false + + @see PxGeometry PxGeometryType getGeometryType() + */ + virtual bool getHeightFieldGeometry(PxHeightFieldGeometry& geometry) const = 0; + + /** + \brief Retrieves the actor which this shape is associated with. + + \return The actor this shape is associated with, if it is an exclusive shape, else NULL + + @see PxRigidStatic, PxRigidDynamic, PxArticulationLink + */ + virtual PxRigidActor* getActor() const = 0; + + +/************************************************************************************************/ + +/** @name Pose Manipulation +*/ +//@{ + + /** + \brief Sets the pose of the shape in actor space, i.e. relative to the actors to which they are attached. + + This transformation is identity by default. + + The local pose is an attribute of the shape, and so will apply to all actors to which the shape is attached. + + Sleeping: Does NOT wake the associated actor up automatically. + + Note: Does not automatically update the inertia properties of the owning actor (if applicable); use the + PhysX extensions method #PxRigidBodyExt::updateMassAndInertia() to do this. + + Default: the identity transform + + \param[in] pose The new transform from the actor frame to the shape frame. Range: rigid body transform + + @see getLocalPose() + */ + virtual void setLocalPose(const PxTransform& pose) = 0; + + /** + \brief Retrieves the pose of the shape in actor space, i.e. relative to the actor they are owned by. + + This transformation is identity by default. + + \return Pose of shape relative to the actor's frame. + + @see setLocalPose() + */ + virtual PxTransform getLocalPose() const = 0; + +//@} +/************************************************************************************************/ + +/** @name Collision Filtering +*/ +//@{ + + /** + \brief Sets the user definable collision filter data. + + Sleeping: Does wake up the actor if the filter data change causes a formerly suppressed + collision pair to be enabled. + + Default: (0,0,0,0) + + @see getSimulationFilterData() + */ + virtual void setSimulationFilterData(const PxFilterData& data) = 0; + + /** + \brief Retrieves the shape's collision filter data. + + @see setSimulationFilterData() + */ + virtual PxFilterData getSimulationFilterData() const = 0; + + /** + \brief Sets the user definable query filter data. + + Default: (0,0,0,0) + + @see getQueryFilterData() + */ + virtual void setQueryFilterData(const PxFilterData& data) = 0; + + /** + \brief Retrieves the shape's Query filter data. + + @see setQueryFilterData() + */ + virtual PxFilterData getQueryFilterData() const = 0; + +//@} +/************************************************************************************************/ + + /** + \brief Assigns material(s) to the shape. + + Sleeping: Does NOT wake the associated actor up automatically. + + \param[in] materials List of material pointers to assign to the shape. See #PxMaterial + \param[in] materialCount The number of materials provided. + + @see PxPhysics.createMaterial() getMaterials() + */ + virtual void setMaterials(PxMaterial*const* materials, PxU16 materialCount) = 0; + + /** + \brief Returns the number of materials assigned to the shape. + + You can use #getMaterials() to retrieve the material pointers. + + \return Number of materials associated with this shape. + + @see PxMaterial getMaterials() + */ + virtual PxU16 getNbMaterials() const = 0; + + /** + \brief Retrieve all the material pointers associated with the shape. + + You can retrieve the number of material pointers by calling #getNbMaterials() + + Note: Removing materials with #PxMaterial::release() will invalidate the pointer of the released material. + + \param[out] userBuffer The buffer to store the material pointers. + \param[in] bufferSize Size of provided user buffer. + \param[in] startIndex Index of first material pointer to be retrieved + \return Number of material pointers written to the buffer. + + @see PxMaterial getNbMaterials() PxMaterial::release() + */ + virtual PxU32 getMaterials(PxMaterial** userBuffer, PxU32 bufferSize, PxU32 startIndex=0) const = 0; + + /** + \brief Retrieve material from given triangle index. + + The input index is the internal triangle index as used inside the SDK. This is the index + returned to users by various SDK functions such as raycasts. + + This function is only useful for triangle meshes or heightfields, which have per-triangle + materials. For other shapes the function returns the single material associated with the + shape, regardless of the index. + + \param[in] faceIndex The internal triangle index whose material you want to retrieve. + \return Material from input triangle + + \note If faceIndex value of 0xFFFFffff is passed as an input for mesh and heightfield shapes, this function will issue a warning and return NULL. + \note Scene queries set the value of PxQueryHit::faceIndex to 0xFFFFffff whenever it is undefined or does not apply. + + @see PxMaterial getNbMaterials() PxMaterial::release() + */ + virtual PxMaterial* getMaterialFromInternalFaceIndex(PxU32 faceIndex) const = 0; + + /** + \brief Sets the contact offset. + + Shapes whose distance is less than the sum of their contactOffset values will generate contacts. The contact offset must be positive and + greater than the rest offset. Having a contactOffset greater than than the restOffset allows the collision detection system to + predictively enforce the contact constraint even when the objects are slightly separated. This prevents jitter that would occur + if the constraint were enforced only when shapes were within the rest distance. + + Default: 0.02f * PxTolerancesScale::length + + Sleeping: Does NOT wake the associated actor up automatically. + + \param[in] contactOffset Range: [maximum(0,restOffset), PX_MAX_F32) + + @see getContactOffset PxTolerancesScale setRestOffset + */ + virtual void setContactOffset(PxReal contactOffset) = 0; + + /** + \brief Retrieves the contact offset. + + \return The contact offset of the shape. + + @see setContactOffset() + */ + virtual PxReal getContactOffset() const = 0; + + /** + \brief Sets the rest offset. + + Two shapes will come to rest at a distance equal to the sum of their restOffset values. If the restOffset is 0, they should converge to touching + exactly. Having a restOffset greater than zero is useful to have objects slide smoothly, so that they do not get hung up on irregularities of + each others' surfaces. + + Default: 0.0f + + Sleeping: Does NOT wake the associated actor up automatically. + + \param[in] restOffset Range: (-PX_MAX_F32, contactOffset) + + @see getRestOffset setContactOffset + */ + virtual void setRestOffset(PxReal restOffset) = 0; + + /** + \brief Retrieves the rest offset. + + \return The rest offset of the shape. + + @see setRestOffset() + */ + virtual PxReal getRestOffset() const = 0; + + + /** + \brief Sets torsional patch radius. + + This defines the radius of the contact patch used to apply torsional friction. If the radius is 0, no torsional friction + will be applied. If the radius is > 0, some torsional friction will be applied. This is proportional to the penetration depth + so, if the shapes are separated or penetration is zero, no torsional friction will be applied. It is used to approximate + rotational friction introduced by the compression of contacting surfaces. + + \param[in] radius Range: (0, PX_MAX_F32) + + */ + virtual void setTorsionalPatchRadius(PxReal radius) = 0; + + /** + \brief Gets torsional patch radius. + + This defines the radius of the contact patch used to apply torsional friction. If the radius is 0, no torsional friction + will be applied. If the radius is > 0, some torsional friction will be applied. This is proportional to the penetration depth + so, if the shapes are separated or penetration is zero, no torsional friction will be applied. It is used to approximate + rotational friction introduced by the compression of contacting surfaces. + + \return The torsional patch radius of the shape. + */ + virtual PxReal getTorsionalPatchRadius() const = 0; + + /** + \brief Sets minimum torsional patch radius. + + This defines the minimum radius of the contact patch used to apply torsional friction. If the radius is 0, the amount of torsional friction + that will be applied will be entirely dependent on the value of torsionalPatchRadius. + + If the radius is > 0, some torsional friction will be applied regardless of the value of torsionalPatchRadius or the amount of penetration. + + \param[in] radius Range: (0, PX_MAX_F32) + + */ + virtual void setMinTorsionalPatchRadius(PxReal radius) = 0; + + /** + \brief Gets minimum torsional patch radius. + + This defines the minimum radius of the contact patch used to apply torsional friction. If the radius is 0, the amount of torsional friction + that will be applied will be entirely dependent on the value of torsionalPatchRadius. + + If the radius is > 0, some torsional friction will be applied regardless of the value of torsionalPatchRadius or the amount of penetration. + + \return The minimum torsional patch radius of the shape. + */ + virtual PxReal getMinTorsionalPatchRadius() const = 0; + + +/************************************************************************************************/ + + /** + \brief Sets shape flags + + Sleeping: Does NOT wake the associated actor up automatically. + + \param[in] flag The shape flag to enable/disable. See #PxShapeFlag. + \param[in] value True to set the flag. False to clear the flag specified in flag. + + Default: PxShapeFlag::eVISUALIZATION | PxShapeFlag::eSIMULATION_SHAPE | PxShapeFlag::eSCENE_QUERY_SHAPE + + @see PxShapeFlag getFlags() + */ + virtual void setFlag(PxShapeFlag::Enum flag, bool value) = 0; + + /** + \brief Sets shape flags + + @see PxShapeFlag getFlags() + */ + virtual void setFlags(PxShapeFlags inFlags) = 0; + + /** + \brief Retrieves shape flags. + + \return The values of the shape flags. + + @see PxShapeFlag setFlag() + */ + virtual PxShapeFlags getFlags() const = 0; + + /** + \brief Returns true if the shape is exclusive to an actor. + + @see PxPhysics::createShape() + */ + virtual bool isExclusive() const = 0; + + /** + \brief Sets a name string for the object that can be retrieved with #getName(). + + This is for debugging and is not used by the SDK. + The string is not copied by the SDK, only the pointer is stored. + + Default: NULL + + \param[in] name The name string to set the objects name to. + + @see getName() + */ + virtual void setName(const char* name) = 0; + + + /** + \brief retrieves the name string set with setName(). + \return The name associated with the shape. + + @see setName() + */ + virtual const char* getName() const = 0; + + + virtual const char* getConcreteTypeName() const { return "PxShape"; } + +/************************************************************************************************/ + + void* userData; //!< user can assign this to whatever, usually to create a 1:1 relationship with a user object. + +protected: + PX_INLINE PxShape(PxBaseFlags baseFlags) : PxBase(baseFlags) {} + PX_INLINE PxShape(PxType concreteType, PxBaseFlags baseFlags) : PxBase(concreteType, baseFlags), userData(NULL) {} + virtual ~PxShape() {} + virtual bool isKindOf(const char* name) const { return !::strcmp("PxShape", name) || PxBase::isKindOf(name); } + +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/PxSimulationEventCallback.h b/sources/PhysX/PhysX/include/PxSimulationEventCallback.h new file mode 100644 index 00000000..e242d45b --- /dev/null +++ b/sources/PhysX/PhysX/include/PxSimulationEventCallback.h @@ -0,0 +1,915 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_SIMULATION_EVENT_CALLBACK +#define PX_SIMULATION_EVENT_CALLBACK +/** \addtogroup physics +@{ +*/ + +#include "foundation/PxVec3.h" +#include "foundation/PxTransform.h" +#include "foundation/PxMemory.h" +#include "PxPhysXConfig.h" +#include "PxFiltering.h" +#include "PxContact.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxShape; +class PxActor; +class PxRigidActor; +class PxRigidBody; +class PxConstraint; + + +/** +\brief Extra data item types for contact pairs. + +@see PxContactPairExtraDataItem.type +*/ +struct PxContactPairExtraDataType +{ + enum Enum + { + ePRE_SOLVER_VELOCITY, //!< see #PxContactPairVelocity + ePOST_SOLVER_VELOCITY, //!< see #PxContactPairVelocity + eCONTACT_EVENT_POSE, //!< see #PxContactPairPose + eCONTACT_PAIR_INDEX //!< see #PxContactPairIndex + }; +}; + + +/** +\brief Base class for items in the extra data stream of contact pairs + +@see PxContactPairHeader.extraDataStream +*/ +struct PxContactPairExtraDataItem +{ +public: + PX_FORCE_INLINE PxContactPairExtraDataItem() {} + + /** + \brief The type of the extra data stream item + */ + PxU8 type; +}; + + +/** +\brief Velocities of the contact pair rigid bodies + +This struct is shared by multiple types of extra data items. The #type field allows to distinguish between them: +\li PxContactPairExtraDataType::ePRE_SOLVER_VELOCITY: see #PxPairFlag::ePRE_SOLVER_VELOCITY +\li PxContactPairExtraDataType::ePOST_SOLVER_VELOCITY: see #PxPairFlag::ePOST_SOLVER_VELOCITY + +\note For static rigid bodies, the velocities will be set to zero. + +@see PxContactPairHeader.extraDataStream +*/ +struct PxContactPairVelocity : public PxContactPairExtraDataItem +{ +public: + PX_FORCE_INLINE PxContactPairVelocity() {} + + /** + \brief The linear velocity of the rigid bodies + */ + PxVec3 linearVelocity[2]; + + /** + \brief The angular velocity of the rigid bodies + */ + PxVec3 angularVelocity[2]; +}; + + +/** +\brief World space actor poses of the contact pair rigid bodies + +@see PxContactPairHeader.extraDataStream PxPairFlag::eCONTACT_EVENT_POSE +*/ +struct PxContactPairPose : public PxContactPairExtraDataItem +{ +public: + PX_FORCE_INLINE PxContactPairPose() {} + + /** + \brief The world space pose of the rigid bodies + */ + PxTransform globalPose[2]; +}; + + +/** +\brief Marker for the beginning of a new item set in the extra data stream. + +If CCD with multiple passes is enabled, then a fast moving object might bounce on and off the same +object multiple times. Also, different shapes of the same actor might gain and lose contact with an other +object over multiple passes. This marker allows to seperate the extra data items for each collision case, as well as +distinguish the shape pair reports of different CCD passes. + +Example: +Let us assume that an actor a0 with shapes s0_0 and s0_1 hits another actor a1 with shape s1. +First s0_0 will hit s1, then a0 will slightly rotate and s0_1 will hit s1 while s0_0 will lose contact with s1. +Furthermore, let us say that contact event pose information is requested as extra data. +The extra data stream will look like this: + +PxContactPairIndexA | PxContactPairPoseA | PxContactPairIndexB | PxContactPairPoseB + +The corresponding array of PxContactPair events (see #PxSimulationEventCallback.onContact()) will look like this: + +PxContactPair(touch_found: s0_0, s1) | PxContactPair(touch_lost: s0_0, s1) | PxContactPair(touch_found: s0_1, s1) + +The #index of PxContactPairIndexA will point to the first entry in the PxContactPair array, for PxContactPairIndexB, +#index will point to the third entry. + +@see PxContactPairHeader.extraDataStream +*/ +struct PxContactPairIndex : public PxContactPairExtraDataItem +{ +public: + PX_FORCE_INLINE PxContactPairIndex() {} + + /** + \brief The next item set in the extra data stream refers to the contact pairs starting at #index in the reported PxContactPair array. + */ + PxU16 index; +}; + + +/** +\brief A class to iterate over a contact pair extra data stream. + +@see PxContactPairHeader.extraDataStream +*/ +struct PxContactPairExtraDataIterator +{ + /** + \brief Constructor + \param[in] stream Pointer to the start of the stream. + \param[in] size Size of the stream in bytes. + */ + PX_FORCE_INLINE PxContactPairExtraDataIterator(const PxU8* stream, PxU32 size) + : currPtr(stream), endPtr(stream + size), contactPairIndex(0) + { + clearDataPtrs(); + } + + /** + \brief Advances the iterator to next set of extra data items. + + The contact pair extra data stream contains sets of items as requested by the corresponding #PxPairFlag flags + #PxPairFlag::ePRE_SOLVER_VELOCITY, #PxPairFlag::ePOST_SOLVER_VELOCITY, #PxPairFlag::eCONTACT_EVENT_POSE. A set can contain one + item of each plus the PxContactPairIndex item. This method parses the stream and points the iterator + member variables to the corresponding items of the current set, if they are available. If CCD is not enabled, + you should only get one set of items. If CCD with multiple passes is enabled, you might get more than one item + set. + + \note Even though contact pair extra data is requested per shape pair, you will not get an item set per shape pair + but one per actor pair. If, for example, an actor has two shapes and both collide with another actor, then + there will only be one item set (since it applies to both shape pairs). + + \return True if there was another set of extra data items in the stream, else false. + + @see PxContactPairVelocity PxContactPairPose PxContactPairIndex + */ + PX_INLINE bool nextItemSet() + { + clearDataPtrs(); + + bool foundEntry = false; + bool endOfItemSet = false; + while ((currPtr < endPtr) && (!endOfItemSet)) + { + const PxContactPairExtraDataItem* edItem = reinterpret_cast(currPtr); + PxU8 type = edItem->type; + + switch(type) + { + case PxContactPairExtraDataType::ePRE_SOLVER_VELOCITY: + { + PX_ASSERT(!preSolverVelocity); + preSolverVelocity = static_cast(edItem); + currPtr += sizeof(PxContactPairVelocity); + foundEntry = true; + } + break; + + case PxContactPairExtraDataType::ePOST_SOLVER_VELOCITY: + { + postSolverVelocity = static_cast(edItem); + currPtr += sizeof(PxContactPairVelocity); + foundEntry = true; + } + break; + + case PxContactPairExtraDataType::eCONTACT_EVENT_POSE: + { + eventPose = static_cast(edItem); + currPtr += sizeof(PxContactPairPose); + foundEntry = true; + } + break; + + case PxContactPairExtraDataType::eCONTACT_PAIR_INDEX: + { + if (!foundEntry) + { + contactPairIndex = static_cast(edItem)->index; + currPtr += sizeof(PxContactPairIndex); + foundEntry = true; + } + else + endOfItemSet = true; + } + break; + + default: + return foundEntry; + } + } + + return foundEntry; + } + +private: + /** + \brief Internal helper + */ + PX_FORCE_INLINE void clearDataPtrs() + { + preSolverVelocity = NULL; + postSolverVelocity = NULL; + eventPose = NULL; + } + +public: + /** + \brief Current pointer in the stream. + */ + const PxU8* currPtr; + + /** + \brief Pointer to the end of the stream. + */ + const PxU8* endPtr; + + /** + \brief Pointer to the current pre solver velocity item in the stream. NULL if there is none. + + @see PxContactPairVelocity + */ + const PxContactPairVelocity* preSolverVelocity; + + /** + \brief Pointer to the current post solver velocity item in the stream. NULL if there is none. + + @see PxContactPairVelocity + */ + const PxContactPairVelocity* postSolverVelocity; + + /** + \brief Pointer to the current contact event pose item in the stream. NULL if there is none. + + @see PxContactPairPose + */ + const PxContactPairPose* eventPose; + + /** + \brief The contact pair index of the current item set in the stream. + + @see PxContactPairIndex + */ + PxU32 contactPairIndex; +}; + + +/** +\brief Collection of flags providing information on contact report pairs. + +@see PxContactPairHeader +*/ +struct PxContactPairHeaderFlag +{ + enum Enum + { + eREMOVED_ACTOR_0 = (1<<0), //!< The actor with index 0 has been removed from the scene. + eREMOVED_ACTOR_1 = (1<<1) //!< The actor with index 1 has been removed from the scene. + }; +}; + +/** +\brief Bitfield that contains a set of raised flags defined in PxContactPairHeaderFlag. + +@see PxContactPairHeaderFlag +*/ +typedef PxFlags PxContactPairHeaderFlags; +PX_FLAGS_OPERATORS(PxContactPairHeaderFlag::Enum, PxU16) + + +/** +\brief An Instance of this class is passed to PxSimulationEventCallback.onContact(). + +@see PxSimulationEventCallback.onContact() +*/ +struct PxContactPairHeader +{ + public: + PX_INLINE PxContactPairHeader() {} + + /** + \brief The two actors of the notification shape pairs. + + \note The actor pointers might reference deleted actors. This will be the case if PxPairFlag::eNOTIFY_TOUCH_LOST + or PxPairFlag::eNOTIFY_THRESHOLD_FORCE_LOST events were requested for the pair and one of the involved actors + gets deleted or removed from the scene. Check the #flags member to see whether that is the case. + Do not dereference a pointer to a deleted actor. The pointer to a deleted actor is only provided + such that user data structures which might depend on the pointer value can be updated. + + @see PxActor + */ + PxRigidActor* actors[2]; + + /** + \brief Stream containing extra data as requested in the PxPairFlag flags of the simulation filter. + + This pointer is only valid if any kind of extra data information has been requested for the contact report pair (see #PxPairFlag::ePOST_SOLVER_VELOCITY etc.), + else it will be NULL. + + @see PxPairFlag + */ + const PxU8* extraDataStream; + + /** + \brief Size of the extra data stream [bytes] + */ + PxU16 extraDataStreamSize; + + /** + \brief Additional information on the contact report pair. + + @see PxContactPairHeaderFlag + */ + PxContactPairHeaderFlags flags; + + /** + \brief pointer to the contact pairs + */ + const struct PxContactPair* pairs; + + /** + \brief number of contact pairs + */ + PxU32 nbPairs; +}; + + +/** +\brief Collection of flags providing information on contact report pairs. + +@see PxContactPair +*/ +struct PxContactPairFlag +{ + enum Enum + { + /** + \brief The shape with index 0 has been removed from the actor/scene. + */ + eREMOVED_SHAPE_0 = (1<<0), + + /** + \brief The shape with index 1 has been removed from the actor/scene. + */ + eREMOVED_SHAPE_1 = (1<<1), + + /** + \brief First actor pair contact. + + The provided shape pair marks the first contact between the two actors, no other shape pair has been touching prior to the current simulation frame. + + \note: This info is only available if #PxPairFlag::eNOTIFY_TOUCH_FOUND has been declared for the pair. + */ + eACTOR_PAIR_HAS_FIRST_TOUCH = (1<<2), + + /** + \brief All contact between the actor pair was lost. + + All contact between the two actors has been lost, no shape pairs remain touching after the current simulation frame. + */ + eACTOR_PAIR_LOST_TOUCH = (1<<3), + + /** + \brief Internal flag, used by #PxContactPair.extractContacts() + + The applied contact impulses are provided for every contact point. + This is the case if #PxPairFlag::eSOLVE_CONTACT has been set for the pair. + */ + eINTERNAL_HAS_IMPULSES = (1<<4), + + /** + \brief Internal flag, used by #PxContactPair.extractContacts() + + The provided contact point information is flipped with regards to the shapes of the contact pair. This mainly concerns the order of the internal triangle indices. + */ + eINTERNAL_CONTACTS_ARE_FLIPPED = (1<<5) + }; +}; + +/** +\brief Bitfield that contains a set of raised flags defined in PxContactPairFlag. + +@see PxContactPairFlag +*/ +typedef PxFlags PxContactPairFlags; +PX_FLAGS_OPERATORS(PxContactPairFlag::Enum, PxU16) + + +/** +\brief A contact point as used by contact notification +*/ +struct PxContactPairPoint +{ + /** + \brief The position of the contact point between the shapes, in world space. + */ + PxVec3 position; + + /** + \brief The separation of the shapes at the contact point. A negative separation denotes a penetration. + */ + PxReal separation; + + /** + \brief The normal of the contacting surfaces at the contact point. The normal direction points from the second shape to the first shape. + */ + PxVec3 normal; + + /** + \brief The surface index of shape 0 at the contact point. This is used to identify the surface material. + */ + PxU32 internalFaceIndex0; + + /** + \brief The impulse applied at the contact point, in world space. Divide by the simulation time step to get a force value. + */ + PxVec3 impulse; + + /** + \brief The surface index of shape 1 at the contact point. This is used to identify the surface material. + */ + PxU32 internalFaceIndex1; +}; + + +/** +\brief Contact report pair information. + +Instances of this class are passed to PxSimulationEventCallback.onContact(). If contact reports have been requested for a pair of shapes (see #PxPairFlag), +then the corresponding contact information will be provided through this structure. + +@see PxSimulationEventCallback.onContact() +*/ +struct PxContactPair +{ + public: + PX_INLINE PxContactPair() {} + + /** + \brief The two shapes that make up the pair. + + \note The shape pointers might reference deleted shapes. This will be the case if #PxPairFlag::eNOTIFY_TOUCH_LOST + or #PxPairFlag::eNOTIFY_THRESHOLD_FORCE_LOST events were requested for the pair and one of the involved shapes + gets deleted. Check the #flags member to see whether that is the case. Do not dereference a pointer to a + deleted shape. The pointer to a deleted shape is only provided such that user data structures which might + depend on the pointer value can be updated. + + @see PxShape + */ + PxShape* shapes[2]; + + /** + \brief Pointer to first patch header in contact stream containing contact patch data + + This pointer is only valid if contact point information has been requested for the contact report pair (see #PxPairFlag::eNOTIFY_CONTACT_POINTS). + Use #extractContacts() as a reference for the data layout of the stream. + */ + const PxU8* contactPatches; + + /** + \brief Pointer to first contact point in contact stream containing contact data + + This pointer is only valid if contact point information has been requested for the contact report pair (see #PxPairFlag::eNOTIFY_CONTACT_POINTS). + Use #extractContacts() as a reference for the data layout of the stream. + */ + const PxU8* contactPoints; + + /** + \brief Buffer containing applied impulse data. + + This pointer is only valid if contact point information has been requested for the contact report pair (see #PxPairFlag::eNOTIFY_CONTACT_POINTS). + Use #extractContacts() as a reference for the data layout of the stream. + */ + const PxReal* contactImpulses; + + /** + \brief Size of the contact stream [bytes] including force buffer + */ + PxU32 requiredBufferSize; + + /** + \brief Number of contact points stored in the contact stream + */ + PxU8 contactCount; + + /** + \brief Number of contact patches stored in the contact stream + */ + + PxU8 patchCount; + + /** + \brief Size of the contact stream [bytes] not including force buffer + */ + + PxU16 contactStreamSize; + + /** + \brief Additional information on the contact report pair. + + @see PxContactPairFlag + */ + PxContactPairFlags flags; + + /** + \brief Flags raised due to the contact. + + The events field is a combination of: + +
    +
  • PxPairFlag::eNOTIFY_TOUCH_FOUND,
  • +
  • PxPairFlag::eNOTIFY_TOUCH_PERSISTS,
  • +
  • PxPairFlag::eNOTIFY_TOUCH_LOST,
  • +
  • PxPairFlag::eNOTIFY_TOUCH_CCD,
  • +
  • PxPairFlag::eNOTIFY_THRESHOLD_FORCE_FOUND,
  • +
  • PxPairFlag::eNOTIFY_THRESHOLD_FORCE_PERSISTS,
  • +
  • PxPairFlag::eNOTIFY_THRESHOLD_FORCE_LOST
  • +
+ + See the documentation of #PxPairFlag for an explanation of each. + + \note eNOTIFY_TOUCH_CCD can get raised even if the pair did not request this event. However, in such a case it will only get + raised in combination with one of the other flags to point out that the other event occured during a CCD pass. + + @see PxPairFlag + */ + PxPairFlags events; + + PxU32 internalData[2]; // For internal use only + + /** + \brief Extracts the contact points from the stream and stores them in a convenient format. + + \param[out] userBuffer Array of PxContactPairPoint structures to extract the contact points to. The number of contacts for a pair is defined by #contactCount + \param[in] bufferSize Number of PxContactPairPoint structures the provided buffer can store. + \return Number of contact points written to the buffer. + + @see PxContactPairPoint + */ + PX_INLINE PxU32 extractContacts(PxContactPairPoint* userBuffer, PxU32 bufferSize) const; + + /** + \brief Helper method to clone the contact pair and copy the contact data stream into a user buffer. + + The contact data stream is only accessible during the contact report callback. This helper function provides copy functionality + to buffer the contact stream information such that it can get accessed at a later stage. + + \param[out] newPair The contact pair info will get copied to this instance. The contact data stream pointer of the copy will be redirected to the provided user buffer. Use NULL to skip the contact pair copy operation. + \param[out] bufferMemory Memory block to store the contact data stream to. At most #requiredBufferSize bytes will get written to the buffer. + */ + PX_INLINE void bufferContacts(PxContactPair* newPair, PxU8* bufferMemory) const; + + PX_INLINE const PxU32* getInternalFaceIndices() const; +}; + + +PX_INLINE PxU32 PxContactPair::extractContacts(PxContactPairPoint* userBuffer, PxU32 bufferSize) const +{ + PxU32 nbContacts = 0; + + if(contactCount && bufferSize) + { + PxContactStreamIterator iter(contactPatches, contactPoints, getInternalFaceIndices(), patchCount, contactCount); + + const PxReal* impulses = contactImpulses; + + const PxU32 flippedContacts = (flags & PxContactPairFlag::eINTERNAL_CONTACTS_ARE_FLIPPED); + const PxU32 hasImpulses = (flags & PxContactPairFlag::eINTERNAL_HAS_IMPULSES); + + while(iter.hasNextPatch()) + { + iter.nextPatch(); + while(iter.hasNextContact()) + { + iter.nextContact(); + PxContactPairPoint& dst = userBuffer[nbContacts]; + dst.position = iter.getContactPoint(); + dst.separation = iter.getSeparation(); + dst.normal = iter.getContactNormal(); + if(!flippedContacts) + { + dst.internalFaceIndex0 = iter.getFaceIndex0(); + dst.internalFaceIndex1 = iter.getFaceIndex1(); + } + else + { + dst.internalFaceIndex0 = iter.getFaceIndex1(); + dst.internalFaceIndex1 = iter.getFaceIndex0(); + } + + if(hasImpulses) + { + const PxReal impulse = impulses[nbContacts]; + dst.impulse = dst.normal * impulse; + } + else + dst.impulse = PxVec3(0.0f); + ++nbContacts; + if(nbContacts == bufferSize) + return nbContacts; + } + } + } + + return nbContacts; +} + + +PX_INLINE void PxContactPair::bufferContacts(PxContactPair* newPair, PxU8* bufferMemory) const +{ + PxU8* patches = bufferMemory; + PxU8* contacts = NULL; + if(patches) + { + contacts = bufferMemory + patchCount * sizeof(PxContactPatch); + PxMemCopy(patches, contactPatches, sizeof(PxContactPatch)*patchCount); + PxMemCopy(contacts, contactPoints, contactStreamSize - (sizeof(PxContactPatch)*patchCount)); + } + + if(contactImpulses) + { + PxMemCopy(bufferMemory + ((contactStreamSize + 15) & (~15)), contactImpulses, sizeof(PxReal) * contactCount); + } + + if (newPair) + { + *newPair = *this; + newPair->contactPatches = patches; + newPair->contactPoints = contacts; + } +} + + +PX_INLINE const PxU32* PxContactPair::getInternalFaceIndices() const +{ + return reinterpret_cast(contactImpulses + contactCount); +} + +/** +\brief Collection of flags providing information on trigger report pairs. + +@see PxTriggerPair +*/ +struct PxTriggerPairFlag +{ + enum Enum + { + eREMOVED_SHAPE_TRIGGER = (1<<0), //!< The trigger shape has been removed from the actor/scene. + eREMOVED_SHAPE_OTHER = (1<<1), //!< The shape causing the trigger event has been removed from the actor/scene. + eNEXT_FREE = (1<<2) //!< For internal use only. + }; +}; + +/** +\brief Bitfield that contains a set of raised flags defined in PxTriggerPairFlag. + +@see PxTriggerPairFlag +*/ +typedef PxFlags PxTriggerPairFlags; +PX_FLAGS_OPERATORS(PxTriggerPairFlag::Enum, PxU8) + + +/** +\brief Descriptor for a trigger pair. + +An array of these structs gets passed to the PxSimulationEventCallback::onTrigger() report. + +\note The shape pointers might reference deleted shapes. This will be the case if #PxPairFlag::eNOTIFY_TOUCH_LOST + events were requested for the pair and one of the involved shapes gets deleted. Check the #flags member to see + whether that is the case. Do not dereference a pointer to a deleted shape. The pointer to a deleted shape is + only provided such that user data structures which might depend on the pointer value can be updated. + +@see PxSimulationEventCallback.onTrigger() +*/ +struct PxTriggerPair +{ + PX_INLINE PxTriggerPair() {} + + PxShape* triggerShape; //!< The shape that has been marked as a trigger. + PxRigidActor* triggerActor; //!< The actor to which triggerShape is attached + PxShape* otherShape; //!< The shape causing the trigger event. \deprecated (see #PxSimulationEventCallback::onTrigger()) If collision between trigger shapes is enabled, then this member might point to a trigger shape as well. + PxRigidActor* otherActor; //!< The actor to which otherShape is attached + PxPairFlag::Enum status; //!< Type of trigger event (eNOTIFY_TOUCH_FOUND or eNOTIFY_TOUCH_LOST). eNOTIFY_TOUCH_PERSISTS events are not supported. + PxTriggerPairFlags flags; //!< Additional information on the pair (see #PxTriggerPairFlag) +}; + + +/** +\brief Descriptor for a broken constraint. + +An array of these structs gets passed to the PxSimulationEventCallback::onConstraintBreak() report. + +@see PxConstraint PxSimulationEventCallback.onConstraintBreak() +*/ +struct PxConstraintInfo +{ + PX_INLINE PxConstraintInfo() {} + PX_INLINE PxConstraintInfo(PxConstraint* c, void* extRef, PxU32 t) : constraint(c), externalReference(extRef), type(t) {} + + PxConstraint* constraint; //!< The broken constraint. + void* externalReference; //!< The external object which owns the constraint (see #PxConstraintConnector::getExternalReference()) + PxU32 type; //!< Unique type ID of the external object. Allows to cast the provided external reference to the appropriate type +}; + + +/** +\brief An interface class that the user can implement in order to receive simulation events. + +With the exception of onAdvance(), the events get sent during the call to either #PxScene::fetchResults() or +#PxScene::flushSimulation() with sendPendingReports=true. onAdvance() gets called while the simulation +is running (that is between PxScene::simulate(), onAdvance() and PxScene::fetchResults()). + +\note SDK state should not be modified from within the callbacks. In particular objects should not +be created or destroyed. If state modification is needed then the changes should be stored to a buffer +and performed after the simulation step. + +Threading: With the exception of onAdvance(), it is not necessary to make these callbacks thread safe as +they will only be called in the context of the user thread. + +@see PxScene.setSimulationEventCallback() PxScene.getSimulationEventCallback() +*/ +class PxSimulationEventCallback + { + public: + /** + \brief This is called when a breakable constraint breaks. + + \note The user should not release the constraint shader inside this call! + + \note No event will get reported if the constraint breaks but gets deleted while the time step is still being simulated. + + \param[in] constraints - The constraints which have been broken. + \param[in] count - The number of constraints + + @see PxConstraint PxConstraintDesc.linearBreakForce PxConstraintDesc.angularBreakForce + */ + virtual void onConstraintBreak(PxConstraintInfo* constraints, PxU32 count) = 0; + + /** + \brief This is called with the actors which have just been woken up. + + \note Only supported by rigid bodies yet. + \note Only called on actors for which the PxActorFlag eSEND_SLEEP_NOTIFIES has been set. + \note Only the latest sleep state transition happening between fetchResults() of the previous frame and fetchResults() of the current frame + will get reported. For example, let us assume actor A is awake, then A->putToSleep() gets called, then later A->wakeUp() gets called. + At the next simulate/fetchResults() step only an onWake() event will get triggered because that was the last transition. + \note If an actor gets newly added to a scene with properties such that it is awake and the sleep state does not get changed by + the user or simulation, then an onWake() event will get sent at the next simulate/fetchResults() step. + + \param[in] actors - The actors which just woke up. + \param[in] count - The number of actors + + @see PxScene.setSimulationEventCallback() PxSceneDesc.simulationEventCallback PxActorFlag PxActor.setActorFlag() + */ + virtual void onWake(PxActor** actors, PxU32 count) = 0; + + /** + \brief This is called with the actors which have just been put to sleep. + + \note Only supported by rigid bodies yet. + \note Only called on actors for which the PxActorFlag eSEND_SLEEP_NOTIFIES has been set. + \note Only the latest sleep state transition happening between fetchResults() of the previous frame and fetchResults() of the current frame + will get reported. For example, let us assume actor A is asleep, then A->wakeUp() gets called, then later A->putToSleep() gets called. + At the next simulate/fetchResults() step only an onSleep() event will get triggered because that was the last transition (assuming the simulation + does not wake the actor up). + \note If an actor gets newly added to a scene with properties such that it is asleep and the sleep state does not get changed by + the user or simulation, then an onSleep() event will get sent at the next simulate/fetchResults() step. + + \param[in] actors - The actors which have just been put to sleep. + \param[in] count - The number of actors + + @see PxScene.setSimulationEventCallback() PxSceneDesc.simulationEventCallback PxActorFlag PxActor.setActorFlag() + */ + virtual void onSleep(PxActor** actors, PxU32 count) = 0; + + /** + \brief This is called when certain contact events occur. + + The method will be called for a pair of actors if one of the colliding shape pairs requested contact notification. + You request which events are reported using the filter shader/callback mechanism (see #PxSimulationFilterShader, + #PxSimulationFilterCallback, #PxPairFlag). + + Do not keep references to the passed objects, as they will be + invalid after this function returns. + + \param[in] pairHeader Information on the two actors whose shapes triggered a contact report. + \param[in] pairs The contact pairs of two actors for which contact reports have been requested. See #PxContactPair. + \param[in] nbPairs The number of provided contact pairs. + + @see PxScene.setSimulationEventCallback() PxSceneDesc.simulationEventCallback PxContactPair PxPairFlag PxSimulationFilterShader PxSimulationFilterCallback + */ + virtual void onContact(const PxContactPairHeader& pairHeader, const PxContactPair* pairs, PxU32 nbPairs) = 0; + + /** + \brief This is called with the current trigger pair events. + + Shapes which have been marked as triggers using PxShapeFlag::eTRIGGER_SHAPE will send events + according to the pair flag specification in the filter shader (see #PxPairFlag, #PxSimulationFilterShader). + + \note Trigger shapes will no longer send notification events for interactions with other trigger shapes. + + \param[in] pairs - The trigger pair events. + \param[in] count - The number of trigger pair events. + + @see PxScene.setSimulationEventCallback() PxSceneDesc.simulationEventCallback PxPairFlag PxSimulationFilterShader PxShapeFlag PxShape.setFlag() + */ + virtual void onTrigger(PxTriggerPair* pairs, PxU32 count) = 0; + + /** + \brief Provides early access to the new pose of moving rigid bodies. + + When this call occurs, rigid bodies having the #PxRigidBodyFlag::eENABLE_POSE_INTEGRATION_PREVIEW + flag set, were moved by the simulation and their new poses can be accessed through the provided buffers. + + \note The provided buffers are valid and can be read until the next call to #PxScene::simulate() or #PxScene::collide(). + + \note Buffered user changes to the rigid body pose will not yet be reflected in the provided data. More important, + the provided data might contain bodies that have been deleted while the simulation was running. It is the user's + responsibility to detect and avoid dereferencing such bodies. + + \note This callback gets triggered while the simulation is running. If the provided rigid body references are used to + read properties of the object, then the callback has to guarantee no other thread is writing to the same body at the same + time. + + \note The code in this callback should be lightweight as it can block the simulation, that is, the + #PxScene::fetchResults() call. + + \param[in] bodyBuffer The rigid bodies that moved and requested early pose reporting. + \param[in] poseBuffer The integrated rigid body poses of the bodies listed in bodyBuffer. + \param[in] count The number of entries in the provided buffers. + + @see PxScene.setSimulationEventCallback() PxSceneDesc.simulationEventCallback PxRigidBodyFlag::eENABLE_POSE_INTEGRATION_PREVIEW + */ + virtual void onAdvance(const PxRigidBody*const* bodyBuffer, const PxTransform* poseBuffer, const PxU32 count) = 0; + + virtual ~PxSimulationEventCallback() {} + }; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/PxSimulationStatistics.h b/sources/PhysX/PhysX/include/PxSimulationStatistics.h new file mode 100644 index 00000000..57635e3d --- /dev/null +++ b/sources/PhysX/PhysX/include/PxSimulationStatistics.h @@ -0,0 +1,339 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_SIMULATION_STATISTICS +#define PX_SIMULATION_STATISTICS +/** \addtogroup physics +@{ +*/ + +#include "foundation/PxAssert.h" +#include "PxPhysXConfig.h" +#include "geometry/PxGeometry.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief Class used to retrieve statistics for a simulation step. + +@see PxScene::getSimulationStatistics() +*/ +class PxSimulationStatistics +{ +public: + + /** + \brief Different types of rigid body collision pair statistics. + @see getRbPairStats + */ + enum RbPairStatsType + { + /** + \brief Shape pairs processed as discrete contact pairs for the current simulation step. + */ + eDISCRETE_CONTACT_PAIRS, + + /** + \brief Shape pairs processed as swept integration pairs for the current simulation step. + + \note Counts the pairs for which special CCD (continuous collision detection) work was actually done and NOT the number of pairs which were configured for CCD. + Furthermore, there can be multiple CCD passes and all processed pairs of all passes are summed up, hence the number can be larger than the amount of pairs which have been configured for CCD. + + @see PxPairFlag::eDETECT_CCD_CONTACT, + */ + eCCD_PAIRS, + + /** + \brief Shape pairs processed with user contact modification enabled for the current simulation step. + + @see PxContactModifyCallback + */ + eMODIFIED_CONTACT_PAIRS, + + /** + \brief Trigger shape pairs processed for the current simulation step. + + @see PxShapeFlag::eTRIGGER_SHAPE + */ + eTRIGGER_PAIRS + }; + + +//objects: + /** + \brief Number of active PxConstraint objects (joints etc.) for the current simulation step. + */ + PxU32 nbActiveConstraints; + + /** + \brief Number of active dynamic bodies for the current simulation step. + + \note Does not include active kinematic bodies + */ + PxU32 nbActiveDynamicBodies; + + /** + \brief Number of active kinematic bodies for the current simulation step. + + \note Kinematic deactivation occurs at the end of the frame after the last call to PxRigidDynamic::setKinematicTarget() was called so kinematics that are + deactivated in a given frame will be included by this counter. + */ + PxU32 nbActiveKinematicBodies; + + /** + \brief Number of static bodies for the current simulation step. + */ + PxU32 nbStaticBodies; + + /** + \brief Number of dynamic bodies for the current simulation step. + + \note Includes inactive bodies and articulation links + \note Does not include kinematic bodies + */ + PxU32 nbDynamicBodies; + + /** + \brief Number of kinematic bodies for the current simulation step. + + \note Includes inactive bodies + */ + PxU32 nbKinematicBodies; + + /** + \brief Number of shapes of each geometry type. + */ + + PxU32 nbShapes[PxGeometryType::eGEOMETRY_COUNT]; + + /** + \brief Number of aggregates in the scene. + */ + PxU32 nbAggregates; + + /** + \brief Number of articulations in the scene. + */ + PxU32 nbArticulations; + +//solver: + /** + \brief The number of 1D axis constraints(joints+contact) present in the current simulation step. + */ + PxU32 nbAxisSolverConstraints; + + /** + \brief The size (in bytes) of the compressed contact stream in the current simulation step + */ + PxU32 compressedContactSize; + + /** + \brief The total required size (in bytes) of the contact constraints in the current simulation step + */ + PxU32 requiredContactConstraintMemory; + + /** + \brief The peak amount of memory (in bytes) that was allocated for constraints (this includes joints) in the current simulation step + */ + PxU32 peakConstraintMemory; + +//broadphase: + /** + \brief Get number of broadphase volumes added for the current simulation step. + + \return Number of broadphase volumes added. + */ + PX_FORCE_INLINE PxU32 getNbBroadPhaseAdds() const + { + return nbBroadPhaseAdds; + } + + /** + \brief Get number of broadphase volumes removed for the current simulation step. + + \return Number of broadphase volumes removed. + */ + PX_FORCE_INLINE PxU32 getNbBroadPhaseRemoves() const + { + return nbBroadPhaseRemoves; + } + +//collisions: + /** + \brief Get number of shape collision pairs of a certain type processed for the current simulation step. + + There is an entry for each geometry pair type. + + \note entry[i][j] = entry[j][i], hence, if you want the sum of all pair + types, you need to discard the symmetric entries + + \param[in] pairType The type of pair for which to get information + \param[in] g0 The geometry type of one pair object + \param[in] g1 The geometry type of the other pair object + \return Number of processed pairs of the specified geometry types. + */ + PxU32 getRbPairStats(RbPairStatsType pairType, PxGeometryType::Enum g0, PxGeometryType::Enum g1) const + { + PX_ASSERT_WITH_MESSAGE( (pairType >= eDISCRETE_CONTACT_PAIRS) && + (pairType <= eTRIGGER_PAIRS), + "Invalid pairType in PxSimulationStatistics::getRbPairStats"); + + if (g0 >= PxGeometryType::eGEOMETRY_COUNT || g1 >= PxGeometryType::eGEOMETRY_COUNT) + { + PX_ASSERT(false); + return 0; + } + + PxU32 nbPairs = 0; + switch(pairType) + { + case eDISCRETE_CONTACT_PAIRS: + nbPairs = nbDiscreteContactPairs[g0][g1]; + break; + case eCCD_PAIRS: + nbPairs = nbCCDPairs[g0][g1]; + break; + case eMODIFIED_CONTACT_PAIRS: + nbPairs = nbModifiedContactPairs[g0][g1]; + break; + case eTRIGGER_PAIRS: + nbPairs = nbTriggerPairs[g0][g1]; + break; + } + return nbPairs; + } + + /** + \brief Total number of (non CCD) pairs reaching narrow phase + */ + PxU32 nbDiscreteContactPairsTotal; + + /** + \brief Total number of (non CCD) pairs for which contacts are successfully cached (<=nbDiscreteContactPairsTotal) + \note This includes pairs for which no contacts are generated, it still counts as a cache hit. + */ + PxU32 nbDiscreteContactPairsWithCacheHits; + + /** + \brief Total number of (non CCD) pairs for which at least 1 contact was generated (<=nbDiscreteContactPairsTotal) + */ + PxU32 nbDiscreteContactPairsWithContacts; + + /** + \brief Number of new pairs found by BP this frame + */ + PxU32 nbNewPairs; + + /** + \brief Number of lost pairs from BP this frame + */ + PxU32 nbLostPairs; + + /** + \brief Number of new touches found by NP this frame + */ + PxU32 nbNewTouches; + + /** + \brief Number of lost touches from NP this frame + */ + PxU32 nbLostTouches; + + /** + \brief Number of partitions used by the solver this frame + */ + PxU32 nbPartitions; + + PxSimulationStatistics() : + nbActiveConstraints (0), + nbActiveDynamicBodies (0), + nbActiveKinematicBodies (0), + nbStaticBodies (0), + nbDynamicBodies (0), + nbKinematicBodies (0), + nbAggregates (0), + nbArticulations (0), + nbAxisSolverConstraints (0), + compressedContactSize (0), + requiredContactConstraintMemory (0), + peakConstraintMemory (0), + nbDiscreteContactPairsTotal (0), + nbDiscreteContactPairsWithCacheHits (0), + nbDiscreteContactPairsWithContacts (0), + nbNewPairs (0), + nbLostPairs (0), + nbNewTouches (0), + nbLostTouches (0), + nbPartitions (0) + { + nbBroadPhaseAdds = 0; + nbBroadPhaseRemoves = 0; + + for(PxU32 i=0; i < PxGeometryType::eGEOMETRY_COUNT; i++) + { + for(PxU32 j=0; j < PxGeometryType::eGEOMETRY_COUNT; j++) + { + nbDiscreteContactPairs[i][j] = 0; + nbModifiedContactPairs[i][j] = 0; + nbCCDPairs[i][j] = 0; + nbTriggerPairs[i][j] = 0; + } + } + + for(PxU32 i=0; i < PxGeometryType::eGEOMETRY_COUNT; i++) + { + nbShapes[i] = 0; + } + } + + + // + // We advise to not access these members directly. Use the provided accessor methods instead. + // +//broadphase: + PxU32 nbBroadPhaseAdds; + PxU32 nbBroadPhaseRemoves; + +//collisions: + PxU32 nbDiscreteContactPairs[PxGeometryType::eGEOMETRY_COUNT][PxGeometryType::eGEOMETRY_COUNT]; + PxU32 nbCCDPairs[PxGeometryType::eGEOMETRY_COUNT][PxGeometryType::eGEOMETRY_COUNT]; + PxU32 nbModifiedContactPairs[PxGeometryType::eGEOMETRY_COUNT][PxGeometryType::eGEOMETRY_COUNT]; + PxU32 nbTriggerPairs[PxGeometryType::eGEOMETRY_COUNT][PxGeometryType::eGEOMETRY_COUNT]; +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/PxVisualizationParameter.h b/sources/PhysX/PhysX/include/PxVisualizationParameter.h new file mode 100644 index 00000000..c05724b2 --- /dev/null +++ b/sources/PhysX/PhysX/include/PxVisualizationParameter.h @@ -0,0 +1,254 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX_DEBUG_VISUALIZATION_PARAMETER +#define PX_PHYSICS_NX_DEBUG_VISUALIZATION_PARAMETER + +#include "foundation/PxPreprocessor.h" + +/** \addtogroup physics +@{ +*/ + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/* +NOTE: Parameters should NOT be conditionally compiled out. Even if a particular feature is not available. +Otherwise the parameter values get shifted about and the numeric values change per platform. This causes problems +when trying to serialize parameters. + +New parameters should also be added to the end of the list for this reason. Also make sure to update +eNUM_VALUES, which should be one higher than the maximum value in the enum. +*/ + +/** +\brief Debug visualization parameters. + +#PxVisualizationParameter::eSCALE is the master switch for enabling visualization, please read the corresponding documentation +for further details. + +@see PxScene.setVisualizationParameter() PxScene.getVisualizationParameter() PxScene.getRenderBuffer() +*/ +struct PxVisualizationParameter +{ + enum Enum + { + /* RigidBody-related parameters */ + + /** + \brief This overall visualization scale gets multiplied with the individual scales. Setting to zero ignores all visualizations. Default is 0. + + The below settings permit the debug visualization of various simulation properties. + The setting is either zero, in which case the property is not drawn. Otherwise it is a scaling factor + that determines the size of the visualization widgets. + + Only objects for which visualization is turned on using setFlag(eVISUALIZATION) are visualized (see #PxActorFlag::eVISUALIZATION, #PxShapeFlag::eVISUALIZATION, ...). + Contacts are visualized if they involve a body which is being visualized. + Default is 0. + + Notes: + - to see any visualization, you have to set PxVisualizationParameter::eSCALE to nonzero first. + - the scale factor has been introduced because it's difficult (if not impossible) to come up with a + good scale for 3D vectors. Normals are normalized and their length is always 1. But it doesn't mean + we should render a line of length 1. Depending on your objects/scene, this might be completely invisible + or extremely huge. That's why the scale factor is here, to let you tune the length until it's ok in + your scene. + - however, things like collision shapes aren't ambiguous. They are clearly defined for example by the + triangles & polygons themselves, and there's no point in scaling that. So the visualization widgets + are only scaled when it makes sense. + + Range: [0, PX_MAX_F32)
+ Default: 0 + */ + eSCALE, + + + /** + \brief Visualize the world axes. + */ + eWORLD_AXES, + + /* Body visualizations */ + + /** + \brief Visualize a bodies axes. + + @see PxActor.globalPose PxActor + */ + eBODY_AXES, + + /** + \brief Visualize a body's mass axes. + + This visualization is also useful for visualizing the sleep state of bodies. Sleeping bodies are drawn in + black, while awake bodies are drawn in white. If the body is sleeping and part of a sleeping group, it is + drawn in red. + + @see PxBodyDesc.massLocalPose PxActor + */ + eBODY_MASS_AXES, + + /** + \brief Visualize the bodies linear velocity. + + @see PxBodyDesc.linearVelocity PxActor + */ + eBODY_LIN_VELOCITY, + + /** + \brief Visualize the bodies angular velocity. + + @see PxBodyDesc.angularVelocity PxActor + */ + eBODY_ANG_VELOCITY, + + + /* Contact visualisations */ + + /** + \brief Visualize contact points. Will enable contact information. + */ + eCONTACT_POINT, + + /** + \brief Visualize contact normals. Will enable contact information. + */ + eCONTACT_NORMAL, + + /** + \brief Visualize contact errors. Will enable contact information. + */ + eCONTACT_ERROR, + + /** + \brief Visualize Contact forces. Will enable contact information. + */ + eCONTACT_FORCE, + + + /** + \brief Visualize actor axes. + + @see PxRigidStatic PxRigidDynamic PxArticulationLink + */ + eACTOR_AXES, + + + /** + \brief Visualize bounds (AABBs in world space) + */ + eCOLLISION_AABBS, + + /** + \brief Shape visualization + + @see PxShape + */ + eCOLLISION_SHAPES, + + /** + \brief Shape axis visualization + + @see PxShape + */ + eCOLLISION_AXES, + + /** + \brief Compound visualization (compound AABBs in world space) + */ + eCOLLISION_COMPOUNDS, + + /** + \brief Mesh & convex face normals + + @see PxTriangleMesh PxConvexMesh + */ + eCOLLISION_FNORMALS, + + /** + \brief Active edges for meshes + + @see PxTriangleMesh + */ + eCOLLISION_EDGES, + + /** + \brief Static pruning structures + */ + eCOLLISION_STATIC, + + /** + \brief Dynamic pruning structures + */ + eCOLLISION_DYNAMIC, + + /** + \brief Visualizes pairwise state. + */ + eDEPRECATED_COLLISION_PAIRS, + + /** + \brief Joint local axes + */ + eJOINT_LOCAL_FRAMES, + + /** + \brief Joint limits + */ + eJOINT_LIMITS, + + /** + \brief Visualize culling box + */ + eCULL_BOX, + + /** + \brief MBP regions + */ + eMBP_REGIONS, + + /** + \brief This is not a parameter, it just records the current number of parameters (as maximum(PxVisualizationParameter)+1) for use in loops. + */ + eNUM_VALUES, + + eFORCE_DWORD = 0x7fffffff + }; +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/characterkinematic/PxBoxController.h b/sources/PhysX/PhysX/include/characterkinematic/PxBoxController.h new file mode 100644 index 00000000..533600b4 --- /dev/null +++ b/sources/PhysX/PhysX/include/characterkinematic/PxBoxController.h @@ -0,0 +1,229 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_CCT_BOX_CONTROLLER +#define PX_PHYSICS_CCT_BOX_CONTROLLER +/** \addtogroup character + @{ +*/ + +#include "characterkinematic/PxController.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief Descriptor for a box character controller. + +@see PxBoxController PxControllerDesc +*/ +class PxBoxControllerDesc : public PxControllerDesc +{ +public: + /** + \brief constructor sets to default. + */ + PX_INLINE PxBoxControllerDesc(); + PX_INLINE virtual ~PxBoxControllerDesc() {} + + /** + \brief copy constructor. + */ + PX_INLINE PxBoxControllerDesc(const PxBoxControllerDesc&); + + /** + \brief assignment operator. + */ + PX_INLINE PxBoxControllerDesc& operator=(const PxBoxControllerDesc&); + + /** + \brief (re)sets the structure to the default. + */ + PX_INLINE virtual void setToDefault(); + + /** + \brief returns true if the current settings are valid + + \return True if the descriptor is valid. + */ + PX_INLINE virtual bool isValid() const; + + /** + \brief Half height + + Default: 1.0 + */ + PxF32 halfHeight; // Half-height in the "up" direction + + /** + \brief Half side extent + + Default: 0.5 + */ + PxF32 halfSideExtent; // Half-extent in the "side" direction + + /** + \brief Half forward extent + + Default: 0.5 + */ + PxF32 halfForwardExtent; // Half-extent in the "forward" direction + +protected: + PX_INLINE void copy(const PxBoxControllerDesc&); +}; + +PX_INLINE PxBoxControllerDesc::PxBoxControllerDesc() : + PxControllerDesc (PxControllerShapeType::eBOX), + halfHeight (1.0f), + halfSideExtent (0.5f), + halfForwardExtent (0.5f) +{ +} + +PX_INLINE PxBoxControllerDesc::PxBoxControllerDesc(const PxBoxControllerDesc& other) : PxControllerDesc(other) +{ + copy(other); +} + +PX_INLINE PxBoxControllerDesc& PxBoxControllerDesc::operator=(const PxBoxControllerDesc& other) +{ + PxControllerDesc::operator=(other); + copy(other); + return *this; +} + +PX_INLINE void PxBoxControllerDesc::copy(const PxBoxControllerDesc& other) +{ + halfHeight = other.halfHeight; + halfSideExtent = other.halfSideExtent; + halfForwardExtent = other.halfForwardExtent; +} + +PX_INLINE void PxBoxControllerDesc::setToDefault() +{ + *this = PxBoxControllerDesc(); +} + +PX_INLINE bool PxBoxControllerDesc::isValid() const +{ + if(!PxControllerDesc::isValid()) return false; + if(halfHeight<=0.0f) return false; + if(halfSideExtent<=0.0f) return false; + if(halfForwardExtent<=0.0f) return false; + if(stepOffset>2.0f*halfHeight) return false; // Prevents obvious mistakes + return true; +} + +/** +\brief Box character controller. + +@see PxBoxControllerDesc PxController +*/ +class PxBoxController : public PxController +{ +public: + + /** + \brief Gets controller's half height. + + \return The half height of the controller. + + @see PxBoxControllerDesc.halfHeight setHalfHeight() + */ + virtual PxF32 getHalfHeight() const = 0; + + /** + \brief Gets controller's half side extent. + + \return The half side extent of the controller. + + @see PxBoxControllerDesc.halfSideExtent setHalfSideExtent() + */ + virtual PxF32 getHalfSideExtent() const = 0; + + /** + \brief Gets controller's half forward extent. + + \return The half forward extent of the controller. + + @see PxBoxControllerDesc.halfForwardExtent setHalfForwardExtent() + */ + virtual PxF32 getHalfForwardExtent() const = 0; + + /** + \brief Sets controller's half height. + + \warning this doesn't check for collisions. + + \param[in] halfHeight The new half height for the controller. + \return Currently always true. + + @see PxBoxControllerDesc.halfHeight getHalfHeight() + */ + virtual bool setHalfHeight(PxF32 halfHeight) = 0; + + /** + \brief Sets controller's half side extent. + + \warning this doesn't check for collisions. + + \param[in] halfSideExtent The new half side extent for the controller. + \return Currently always true. + + @see PxBoxControllerDesc.halfSideExtent getHalfSideExtent() + */ + virtual bool setHalfSideExtent(PxF32 halfSideExtent) = 0; + + /** + \brief Sets controller's half forward extent. + + \warning this doesn't check for collisions. + + \param[in] halfForwardExtent The new half forward extent for the controller. + \return Currently always true. + + @see PxBoxControllerDesc.halfForwardExtent getHalfForwardExtent() + */ + virtual bool setHalfForwardExtent(PxF32 halfForwardExtent) = 0; + +protected: + PX_INLINE PxBoxController() {} + virtual ~PxBoxController() {} +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/characterkinematic/PxCapsuleController.h b/sources/PhysX/PhysX/include/characterkinematic/PxCapsuleController.h new file mode 100644 index 00000000..cd95d7b6 --- /dev/null +++ b/sources/PhysX/PhysX/include/characterkinematic/PxCapsuleController.h @@ -0,0 +1,250 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_CCT_CAPSULE_CONTROLLER +#define PX_PHYSICS_CCT_CAPSULE_CONTROLLER +/** \addtogroup character + @{ +*/ + +#include "characterkinematic/PxController.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +struct PxCapsuleClimbingMode +{ + enum Enum + { + eEASY, //!< Standard mode, let the capsule climb over surfaces according to impact normal + eCONSTRAINED, //!< Constrained mode, try to limit climbing according to the step offset + + eLAST + }; +}; + +/** +\brief A descriptor for a capsule character controller. + +@see PxCapsuleController PxControllerDesc +*/ +class PxCapsuleControllerDesc : public PxControllerDesc +{ +public: + /** + \brief constructor sets to default. + */ + PX_INLINE PxCapsuleControllerDesc (); + PX_INLINE virtual ~PxCapsuleControllerDesc () {} + + /** + \brief copy constructor. + */ + PX_INLINE PxCapsuleControllerDesc(const PxCapsuleControllerDesc&); + + /** + \brief assignment operator. + */ + PX_INLINE PxCapsuleControllerDesc& operator=(const PxCapsuleControllerDesc&); + + /** + \brief (re)sets the structure to the default. + */ + PX_INLINE virtual void setToDefault(); + /** + \brief returns true if the current settings are valid + + \return True if the descriptor is valid. + */ + PX_INLINE virtual bool isValid() const; + + /** + \brief The radius of the capsule + + Default: 0.0 + + @see PxCapsuleController + */ + PxF32 radius; + + /** + \brief The height of the controller + + Default: 0.0 + + @see PxCapsuleController + */ + PxF32 height; + + /** + \brief The climbing mode + + Default: PxCapsuleClimbingMode::eEASY + + @see PxCapsuleController + */ + PxCapsuleClimbingMode::Enum climbingMode; + +protected: + PX_INLINE void copy(const PxCapsuleControllerDesc&); +}; + +PX_INLINE PxCapsuleControllerDesc::PxCapsuleControllerDesc () : PxControllerDesc(PxControllerShapeType::eCAPSULE) +{ + radius = height = 0.0f; + climbingMode = PxCapsuleClimbingMode::eEASY; +} + +PX_INLINE PxCapsuleControllerDesc::PxCapsuleControllerDesc(const PxCapsuleControllerDesc& other) : PxControllerDesc(other) +{ + copy(other); +} + +PX_INLINE PxCapsuleControllerDesc& PxCapsuleControllerDesc::operator=(const PxCapsuleControllerDesc& other) +{ + PxControllerDesc::operator=(other); + copy(other); + return *this; +} + +PX_INLINE void PxCapsuleControllerDesc::copy(const PxCapsuleControllerDesc& other) +{ + radius = other.radius; + height = other.height; + climbingMode = other.climbingMode; +} + +PX_INLINE void PxCapsuleControllerDesc::setToDefault() +{ + *this = PxCapsuleControllerDesc(); +} + +PX_INLINE bool PxCapsuleControllerDesc::isValid() const +{ + if(!PxControllerDesc::isValid()) return false; + if(radius<=0.0f) return false; + if(height<=0.0f) return false; + if(stepOffset>height+radius*2.0f) return false; // Prevents obvious mistakes + return true; +} +/** +\brief A capsule character controller. + +The capsule is defined as a position, a vertical height, and a radius. +The height is the distance between the two sphere centers at the end of the capsule. +In other words: + +p = pos (returned by controller)
+h = height
+r = radius
+ +p = center of capsule
+top sphere center = p.y + h*0.5
+bottom sphere center = p.y - h*0.5
+top capsule point = p.y + h*0.5 + r
+bottom capsule point = p.y - h*0.5 - r
+*/ +class PxCapsuleController : public PxController +{ +public: + + /** + \brief Gets controller's radius. + + \return The radius of the controller. + + @see PxCapsuleControllerDesc.radius setRadius() + */ + virtual PxF32 getRadius() const = 0; + + /** + \brief Sets controller's radius. + + \warning this doesn't check for collisions. + + \param[in] radius The new radius for the controller. + \return Currently always true. + + @see PxCapsuleControllerDesc.radius getRadius() + */ + virtual bool setRadius(PxF32 radius) = 0; + + /** + \brief Gets controller's height. + + \return The height of the capsule controller. + + @see PxCapsuleControllerDesc.height setHeight() + */ + virtual PxF32 getHeight() const = 0; + + /** + \brief Resets controller's height. + + \warning this doesn't check for collisions. + + \param[in] height The new height for the controller. + \return Currently always true. + + @see PxCapsuleControllerDesc.height getHeight() + */ + virtual bool setHeight(PxF32 height) = 0; + + /** + \brief Gets controller's climbing mode. + + \return The capsule controller's climbing mode. + + @see PxCapsuleControllerDesc.climbingMode setClimbingMode() + */ + virtual PxCapsuleClimbingMode::Enum getClimbingMode() const = 0; + + /** + \brief Sets controller's climbing mode. + + \param[in] mode The capsule controller's climbing mode. + + @see PxCapsuleControllerDesc.climbingMode getClimbingMode() + */ + virtual bool setClimbingMode(PxCapsuleClimbingMode::Enum mode) = 0; + +protected: + PX_INLINE PxCapsuleController() {} + virtual ~PxCapsuleController() {} +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/characterkinematic/PxController.h b/sources/PhysX/PhysX/include/characterkinematic/PxController.h new file mode 100644 index 00000000..3d263bc3 --- /dev/null +++ b/sources/PhysX/PhysX/include/characterkinematic/PxController.h @@ -0,0 +1,916 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_PHYSICS_CCT_CONTROLLER +#define PX_PHYSICS_CCT_CONTROLLER +/** \addtogroup character + @{ +*/ + +#include "characterkinematic/PxExtended.h" +#include "characterkinematic/PxControllerObstacles.h" +#include "PxQueryFiltering.h" +#include "foundation/PxErrorCallback.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief The type of controller, eg box, sphere or capsule. +*/ +struct PxControllerShapeType +{ + enum Enum + { + /** + \brief A box controller. + + @see PxBoxController PxBoxControllerDesc + */ + eBOX, + + /** + \brief A capsule controller + + @see PxCapsuleController PxCapsuleControllerDesc + */ + eCAPSULE, + + eFORCE_DWORD = 0x7fffffff + }; +}; + +class PxShape; +class PxScene; +class PxController; +class PxRigidDynamic; +class PxMaterial; +struct PxFilterData; +class PxQueryFilterCallback; +class PxControllerBehaviorCallback; +class PxObstacleContext; +class PxObstacle; + +/** +\brief specifies how a CCT interacts with non-walkable parts. + +This is only used when slopeLimit is non zero. It is currently enabled for static actors only, and not supported for spheres or capsules. +*/ +struct PxControllerNonWalkableMode +{ + enum Enum + { + ePREVENT_CLIMBING, //!< Stops character from climbing up non-walkable slopes, but doesn't move it otherwise + ePREVENT_CLIMBING_AND_FORCE_SLIDING //!< Stops character from climbing up non-walkable slopes, and forces it to slide down those slopes + }; +}; + +/** +\brief specifies which sides a character is colliding with. +*/ +struct PxControllerCollisionFlag +{ + enum Enum + { + eCOLLISION_SIDES = (1<<0), //!< Character is colliding to the sides. + eCOLLISION_UP = (1<<1), //!< Character has collision above. + eCOLLISION_DOWN = (1<<2) //!< Character has collision below. + }; +}; + +/** +\brief Bitfield that contains a set of raised flags defined in PxControllerCollisionFlag. + +@see PxControllerCollisionFlag +*/ +typedef PxFlags PxControllerCollisionFlags; +PX_FLAGS_OPERATORS(PxControllerCollisionFlag::Enum, PxU8) + +/** +\brief Describes a controller's internal state. +*/ +struct PxControllerState +{ + PxVec3 deltaXP; //!< delta position vector for the object the CCT is standing/riding on. Not always match the CCT delta when variable timesteps are used. + PxShape* touchedShape; //!< Shape on which the CCT is standing + PxRigidActor* touchedActor; //!< Actor owning 'touchedShape' + ObstacleHandle touchedObstacleHandle; // Obstacle on which the CCT is standing + PxU32 collisionFlags; //!< Last known collision flags (PxControllerCollisionFlag) + bool standOnAnotherCCT; //!< Are we standing on another CCT? + bool standOnObstacle; //!< Are we standing on a user-defined obstacle? + bool isMovingUp; //!< is CCT moving up or not? (i.e. explicit jumping) +}; + +/** +\brief Describes a controller's internal statistics. +*/ +struct PxControllerStats +{ + PxU16 nbIterations; + PxU16 nbFullUpdates; + PxU16 nbPartialUpdates; + PxU16 nbTessellation; +}; + +/** +\brief Describes a generic CCT hit. +*/ +struct PxControllerHit +{ + PxController* controller; //!< Current controller + PxExtendedVec3 worldPos; //!< Contact position in world space + PxVec3 worldNormal; //!< Contact normal in world space + PxVec3 dir; //!< Motion direction + PxF32 length; //!< Motion length +}; + +/** +\brief Describes a hit between a CCT and a shape. Passed to onShapeHit() + +@see PxUserControllerHitReport.onShapeHit() +*/ +struct PxControllerShapeHit : public PxControllerHit +{ + PxShape* shape; //!< Touched shape + PxRigidActor* actor; //!< Touched actor + PxU32 triangleIndex; //!< touched triangle index (only for meshes/heightfields) +}; + +/** +\brief Describes a hit between a CCT and another CCT. Passed to onControllerHit(). + +@see PxUserControllerHitReport.onControllerHit() +*/ +struct PxControllersHit : public PxControllerHit +{ + PxController* other; //!< Touched controller +}; + +/** +\brief Describes a hit between a CCT and a user-defined obstacle. Passed to onObstacleHit(). + +@see PxUserControllerHitReport.onObstacleHit() PxObstacleContext +*/ +struct PxControllerObstacleHit : public PxControllerHit +{ + const void* userData; +}; + +/** +\brief User callback class for character controller events. + +\note Character controller hit reports are only generated when move is called. + +@see PxControllerDesc.callback +*/ +class PxUserControllerHitReport +{ +public: + + /** + \brief Called when current controller hits a shape. + + This is called when the CCT moves and hits a shape. This will not be called when a moving shape hits a non-moving CCT. + + \param[in] hit Provides information about the hit. + + @see PxControllerShapeHit + */ + virtual void onShapeHit(const PxControllerShapeHit& hit) = 0; + + /** + \brief Called when current controller hits another controller. + + \param[in] hit Provides information about the hit. + + @see PxControllersHit + */ + virtual void onControllerHit(const PxControllersHit& hit) = 0; + + /** + \brief Called when current controller hits a user-defined obstacle. + + \param[in] hit Provides information about the hit. + + @see PxControllerObstacleHit PxObstacleContext + */ + virtual void onObstacleHit(const PxControllerObstacleHit& hit) = 0; + +protected: + virtual ~PxUserControllerHitReport(){} +}; + + +/** +\brief Dedicated filtering callback for CCT vs CCT. + +This controls collisions between CCTs (one CCT vs anoter CCT). + +To make each CCT collide against all other CCTs, just return true - or simply avoid defining a callback. +To make each CCT freely go through all other CCTs, just return false. +Otherwise create a custom filtering logic in this callback. + +@see PxControllerFilters +*/ +class PxControllerFilterCallback +{ +public: + virtual ~PxControllerFilterCallback(){} + + /** + \brief Filtering method for CCT-vs-CCT. + + \param[in] a First CCT + \param[in] b Second CCT + \return true to keep the pair, false to filter it out + */ + virtual bool filter(const PxController& a, const PxController& b) = 0; +}; + +/** +\brief Filtering data for "move" call. + +This class contains all filtering-related parameters for the PxController::move() call. + +Collisions between a CCT and the world are filtered using the mFilterData, mFilterCallback and mFilterFlags +members. These parameters are internally passed to PxScene::overlap() to find objects touched by the CCT. +Please refer to the PxScene::overlap() documentation for details. + +Collisions between a CCT and another CCT are filtered using the mCCTFilterCallback member. If this filter +callback is not defined, none of the CCT-vs-CCT collisions are filtered, and each CCT will collide against +all other CCTs. + +\note PxQueryFlag::eANY_HIT and PxQueryFlag::eNO_BLOCK are ignored in mFilterFlags. + +@see PxController.move() PxControllerFilterCallback +*/ +class PxControllerFilters +{ + public: + + PX_INLINE PxControllerFilters(const PxFilterData* filterData=NULL, PxQueryFilterCallback* cb=NULL, PxControllerFilterCallback* cctFilterCb=NULL) : + mFilterData (filterData), + mFilterCallback (cb), + mFilterFlags (PxQueryFlag::eSTATIC|PxQueryFlag::eDYNAMIC|PxQueryFlag::ePREFILTER), + mCCTFilterCallback (cctFilterCb) + {} + + // CCT-vs-shapes: + const PxFilterData* mFilterData; //!< Data for internal PxQueryFilterData structure. Passed to PxScene::overlap() call. + //!< This can be NULL, in which case a default PxFilterData is used. + PxQueryFilterCallback* mFilterCallback; //!< Custom filter logic (can be NULL). Passed to PxScene::overlap() call. + PxQueryFlags mFilterFlags; //!< Flags for internal PxQueryFilterData structure. Passed to PxScene::overlap() call. + // CCT-vs-CCT: + PxControllerFilterCallback* mCCTFilterCallback; //!< CCT-vs-CCT filter callback. If NULL, all CCT-vs-CCT collisions are kept. +}; + +/** +\brief Descriptor class for a character controller. + +@see PxBoxController PxCapsuleController +*/ +class PxControllerDesc +{ +public: + + /** + \brief returns true if the current settings are valid + + \return True if the descriptor is valid. + */ + PX_INLINE virtual bool isValid() const; + + /** + \brief Returns the character controller type + + \return The controllers type. + + @see PxControllerType PxCapsuleControllerDesc PxBoxControllerDesc + */ + PX_INLINE PxControllerShapeType::Enum getType() const { return mType; } + + /** + \brief The position of the character + + \note The character's initial position must be such that it does not overlap the static geometry. + + Default: Zero + */ + PxExtendedVec3 position; + + /** + \brief Specifies the 'up' direction + + In order to provide stepping functionality the SDK must be informed about the up direction. + + Default: (0, 1, 0) + + */ + PxVec3 upDirection; + + /** + \brief The maximum slope which the character can walk up. + + In general it is desirable to limit where the character can walk, in particular it is unrealistic + for the character to be able to climb arbitary slopes. + + The limit is expressed as the cosine of desired limit angle. A value of 0 disables this feature. + + \warning It is currently enabled for static actors only (not for dynamic/kinematic actors), and not supported for spheres or capsules. + + Default: 0.707 + + @see upDirection invisibleWallHeight maxJumpHeight + */ + PxF32 slopeLimit; + + /** + \brief Height of invisible walls created around non-walkable triangles + + The library can automatically create invisible walls around non-walkable triangles defined + by the 'slopeLimit' parameter. This defines the height of those walls. If it is 0.0, then + no extra triangles are created. + + Default: 0.0 + + @see upDirection slopeLimit maxJumpHeight + */ + PxF32 invisibleWallHeight; + + /** + \brief Maximum height a jumping character can reach + + This is only used if invisible walls are created ('invisibleWallHeight' is non zero). + + When a character jumps, the non-walkable triangles he might fly over are not found + by the collision queries (since the character's bounding volume does not touch them). + Thus those non-walkable triangles do not create invisible walls, and it is possible + for a jumping character to land on a non-walkable triangle, while he wouldn't have + reached that place by just walking. + + The 'maxJumpHeight' variable is used to extend the size of the collision volume + downward. This way, all the non-walkable triangles are properly found by the collision + queries and it becomes impossible to 'jump over' invisible walls. + + If the character in your game can not jump, it is safe to use 0.0 here. Otherwise it + is best to keep this value as small as possible, since a larger collision volume + means more triangles to process. + + Default: 0.0 + + @see upDirection slopeLimit invisibleWallHeight + */ + PxF32 maxJumpHeight; + + /** + \brief The contact offset used by the controller. + + Specifies a skin around the object within which contacts will be generated. + Use it to avoid numerical precision issues. + + This is dependant on the scale of the users world, but should be a small, positive + non zero value. + + Default: 0.1 + */ + PxF32 contactOffset; + + /** + \brief Defines the maximum height of an obstacle which the character can climb. + + A small value will mean that the character gets stuck and cannot walk up stairs etc, + a value which is too large will mean that the character can climb over unrealistically + high obstacles. + + Default: 0.5 + + @see upDirection + */ + PxF32 stepOffset; + + /** + \brief Density of underlying kinematic actor + + The CCT creates a PhysX's kinematic actor under the hood. This controls its density. + + Default: 10.0 + */ + PxF32 density; + + /** + \brief Scale coefficient for underlying kinematic actor + + The CCT creates a PhysX's kinematic actor under the hood. This controls its scale factor. + This should be a number a bit smaller than 1.0. + + Default: 0.8 + */ + PxF32 scaleCoeff; + + /** + \brief Cached volume growth + + Amount of space around the controller we cache to improve performance. This is a scale factor + that should be higher than 1.0f but not too big, ideally lower than 2.0f. + + Default: 1.5 + */ + PxF32 volumeGrowth; + + /** + \brief Specifies a user report callback. + + This report callback is called when the character collides with shapes and other characters. + + Setting this to NULL disables the callback. + + Default: NULL + + @see PxUserControllerHitReport + */ + PxUserControllerHitReport* reportCallback; + + /** + \brief Specifies a user behavior callback. + + This behavior callback is called to customize the controller's behavior w.r.t. touched shapes. + + Setting this to NULL disables the callback. + + Default: NULL + + @see PxControllerBehaviorCallback + */ + PxControllerBehaviorCallback* behaviorCallback; + + /** + \brief The non-walkable mode controls if a character controller slides or not on a non-walkable part. + + This is only used when slopeLimit is non zero. + + Default: PxControllerNonWalkableMode::ePREVENT_CLIMBING + + @see PxControllerNonWalkableMode + */ + PxControllerNonWalkableMode::Enum nonWalkableMode; + + /** + \brief The material for the actor associated with the controller. + + The controller internally creates a rigid body actor. This parameter specifies the material of the actor. + + Default: NULL + + @see PxMaterial + */ + PxMaterial* material; + + /** + \brief Use a deletion listener to get informed about released objects and clear internal caches if needed. + + If a character controller registers a deletion listener, it will get informed about released objects. That allows the + controller to invalidate cached data that connects to a released object. If a deletion listener is not + registered, PxController::invalidateCache has to be called manually after objects have been released. + + @see PxController::invalidateCache + + Default: true + */ + bool registerDeletionListener; + + /** + \brief User specified data associated with the controller. + + Default: NULL + */ + void* userData; + +protected: + const PxControllerShapeType::Enum mType; //!< The type of the controller. This gets set by the derived class' ctor, the user should not have to change it. + + /** + \brief constructor sets to default. + */ + PX_INLINE PxControllerDesc(PxControllerShapeType::Enum); + PX_INLINE virtual ~PxControllerDesc(); + + /** + \brief copy constructor. + */ + PX_INLINE PxControllerDesc(const PxControllerDesc&); + + /** + \brief assignment operator. + */ + PX_INLINE PxControllerDesc& operator=(const PxControllerDesc&); + + PX_INLINE void copy(const PxControllerDesc&); +}; + +PX_INLINE PxControllerDesc::PxControllerDesc(PxControllerShapeType::Enum t) : mType(t) +{ + upDirection = PxVec3(0.0f, 1.0f, 0.0f); + slopeLimit = 0.707f; + contactOffset = 0.1f; + stepOffset = 0.5f; + density = 10.0f; + scaleCoeff = 0.8f; + volumeGrowth = 1.5f; + reportCallback = NULL; + behaviorCallback = NULL; + userData = NULL; + nonWalkableMode = PxControllerNonWalkableMode::ePREVENT_CLIMBING; + position.x = PxExtended(0.0); + position.y = PxExtended(0.0); + position.z = PxExtended(0.0); + material = NULL; + invisibleWallHeight = 0.0f; + maxJumpHeight = 0.0f; + registerDeletionListener = true; +} + +PX_INLINE PxControllerDesc::PxControllerDesc(const PxControllerDesc& other) : mType(other.mType) +{ + copy(other); +} + +PX_INLINE PxControllerDesc& PxControllerDesc::operator=(const PxControllerDesc& other) +{ + copy(other); + return *this; +} + +PX_INLINE void PxControllerDesc::copy(const PxControllerDesc& other) +{ + upDirection = other.upDirection; + slopeLimit = other.slopeLimit; + contactOffset = other.contactOffset; + stepOffset = other.stepOffset; + density = other.density; + scaleCoeff = other.scaleCoeff; + volumeGrowth = other.volumeGrowth; + reportCallback = other.reportCallback; + behaviorCallback = other.behaviorCallback; + userData = other.userData; + nonWalkableMode = other.nonWalkableMode; + position.x = other.position.x; + position.y = other.position.y; + position.z = other.position.z; + material = other.material; + invisibleWallHeight = other.invisibleWallHeight; + maxJumpHeight = other.maxJumpHeight; + registerDeletionListener = other.registerDeletionListener; +} + +PX_INLINE PxControllerDesc::~PxControllerDesc() +{ +} + +PX_INLINE bool PxControllerDesc::isValid() const +{ + if( mType!=PxControllerShapeType::eBOX + && mType!=PxControllerShapeType::eCAPSULE) + return false; + if(scaleCoeff<0.0f) + return false; + if(volumeGrowth<1.0f) + return false; + if(density<0.0f) + return false; + if(slopeLimit<0.0f) + return false; + if(stepOffset<0.0f) + return false; + if(contactOffset<=0.0f) + return false; + if(!material) + return false; + if(!toVec3(position).isFinite()) + return false; //the float version needs to be finite otherwise actor creation will fail. + + return true; +} + + +/** +\brief Base class for character controllers. + +@see PxCapsuleController PxBoxController +*/ +class PxController +{ +public: + //********************************************************************* + // DEPRECATED FUNCTIONS: + // + // PX_DEPRECATED virtual void setInteraction(PxCCTInteractionMode::Enum flag) = 0; + // PX_DEPRECATED virtual PxCCTInteractionMode::Enum getInteraction() const = 0; + // PX_DEPRECATED virtual void setGroupsBitmask(PxU32 bitmask) = 0; + // PX_DEPRECATED virtual PxU32 getGroupsBitmask() const = 0; + // + // => replaced with: + // + // PxControllerFilters::mCCTFilterCallback. Please define a PxControllerFilterCallback object and emulate the old interaction mode there. + // + //********************************************************************* + + /** + \brief Return the type of controller + + @see PxControllerType + */ + virtual PxControllerShapeType::Enum getType() const = 0; + + /** + \brief Releases the controller. + */ + virtual void release() = 0; + + /** + \brief Moves the character using a "collide-and-slide" algorithm. + + \param[in] disp Displacement vector + \param[in] minDist The minimum travelled distance to consider. If travelled distance is smaller, the character doesn't move. + This is used to stop the recursive motion algorithm when remaining distance to travel is small. + \param[in] elapsedTime Time elapsed since last call + \param[in] filters User-defined filters for this move + \param[in] obstacles Potential additional obstacles the CCT should collide with. + \return Collision flags, collection of ::PxControllerCollisionFlags + */ + virtual PxControllerCollisionFlags move(const PxVec3& disp, PxF32 minDist, PxF32 elapsedTime, const PxControllerFilters& filters, const PxObstacleContext* obstacles=NULL) = 0; + + /** + \brief Sets controller's position. + + The position controlled by this function is the center of the collision shape. + + \warning This is a 'teleport' function, it doesn't check for collisions. + \warning The character's position must be such that it does not overlap the static geometry. + + To move the character under normal conditions use the #move() function. + + \param[in] position The new (center) positon for the controller. + \return Currently always returns true. + + @see PxControllerDesc.position getPosition() getFootPosition() setFootPosition() move() + */ + virtual bool setPosition(const PxExtendedVec3& position) = 0; + + /** + \brief Retrieve the raw position of the controller. + + The position retrieved by this function is the center of the collision shape. To retrieve the bottom position of the shape, + a.k.a. the foot position, use the getFootPosition() function. + + The position is updated by calls to move(). Calling this method without calling + move() will return the last position or the initial position of the controller. + + \return The controller's center position + + @see PxControllerDesc.position setPosition() getFootPosition() setFootPosition() move() + */ + virtual const PxExtendedVec3& getPosition() const = 0; + + /** + \brief Set controller's foot position. + + The position controlled by this function is the bottom of the collision shape, a.k.a. the foot position. + + \note The foot position takes the contact offset into account + + \warning This is a 'teleport' function, it doesn't check for collisions. + + To move the character under normal conditions use the #move() function. + + \param[in] position The new (bottom) positon for the controller. + \return Currently always returns true. + + @see PxControllerDesc.position setPosition() getPosition() getFootPosition() move() + */ + virtual bool setFootPosition(const PxExtendedVec3& position) = 0; + + /** + \brief Retrieve the "foot" position of the controller, i.e. the position of the bottom of the CCT's shape. + + \note The foot position takes the contact offset into account + + \return The controller's foot position + + @see PxControllerDesc.position setPosition() getPosition() setFootPosition() move() + */ + virtual PxExtendedVec3 getFootPosition() const = 0; + + /** + \brief Get the rigid body actor associated with this controller (see PhysX documentation). + The behavior upon manually altering this actor is undefined, you should primarily + use it for reading const properties. + + \return the actor associated with the controller. + */ + virtual PxRigidDynamic* getActor() const = 0; + + /** + \brief The step height. + + \param[in] offset The new step offset for the controller. + + @see PxControllerDesc.stepOffset + */ + virtual void setStepOffset(const PxF32 offset) =0; + + /** + \brief Retrieve the step height. + + \return The step offset for the controller. + + @see setStepOffset() + */ + virtual PxF32 getStepOffset() const =0; + + /** + \brief Sets the non-walkable mode for the CCT. + + \param[in] flag The new value of the non-walkable mode. + + \see PxControllerNonWalkableMode + */ + virtual void setNonWalkableMode(PxControllerNonWalkableMode::Enum flag) = 0; + + /** + \brief Retrieves the non-walkable mode for the CCT. + + \return The current non-walkable mode. + + \see PxControllerNonWalkableMode + */ + virtual PxControllerNonWalkableMode::Enum getNonWalkableMode() const = 0; + + /** + \brief Retrieve the contact offset. + + \return The contact offset for the controller. + + @see PxControllerDesc.contactOffset + */ + virtual PxF32 getContactOffset() const =0; + + /** + \brief Sets the contact offset. + + \param[in] offset The contact offset for the controller. + + @see PxControllerDesc.contactOffset + */ + virtual void setContactOffset(PxF32 offset) =0; + + /** + \brief Retrieve the 'up' direction. + + \return The up direction for the controller. + + @see PxControllerDesc.upDirection + */ + virtual PxVec3 getUpDirection() const =0; + + /** + \brief Sets the 'up' direction. + + \param[in] up The up direction for the controller. + + @see PxControllerDesc.upDirection + */ + virtual void setUpDirection(const PxVec3& up) =0; + + /** + \brief Retrieve the slope limit. + + \return The slope limit for the controller. + + @see PxControllerDesc.slopeLimit + */ + virtual PxF32 getSlopeLimit() const =0; + + /** + \brief Sets the slope limit. + + \note This feature can not be enabled at runtime, i.e. if the slope limit is zero when creating the CCT + (which disables the feature) then changing the slope limit at runtime will not have any effect, and the call + will be ignored. + + \param[in] slopeLimit The slope limit for the controller. + + @see PxControllerDesc.slopeLimit + */ + virtual void setSlopeLimit(PxF32 slopeLimit) =0; + + /** + \brief Flushes internal geometry cache. + + The character controller uses caching in order to speed up collision testing. The cache is + automatically flushed when a change to static objects is detected in the scene. For example when a + static shape is added, updated, or removed from the scene, the cache is automatically invalidated. + + However there may be situations that cannot be automatically detected, and those require manual + invalidation of the cache. Currently the user must call this when the filtering behavior changes (the + PxControllerFilters parameter of the PxController::move call). While the controller in principle + could detect a change in these parameters, it cannot detect a change in the behavior of the filtering + function. + + @see PxController.move + */ + virtual void invalidateCache() = 0; + + /** + \brief Retrieve the scene associated with the controller. + + \return The physics scene + */ + virtual PxScene* getScene() = 0; + + /** + \brief Returns the user data associated with this controller. + + \return The user pointer associated with the controller. + + @see PxControllerDesc.userData + */ + virtual void* getUserData() const = 0; + + /** + \brief Sets the user data associated with this controller. + + \param[in] userData The user pointer associated with the controller. + + @see PxControllerDesc.userData + */ + virtual void setUserData(void* userData) = 0; + + /** + \brief Returns information about the controller's internal state. + + \param[out] state The controller's internal state + + @see PxControllerState + */ + virtual void getState(PxControllerState& state) const = 0; + + /** + \brief Returns the controller's internal statistics. + + \param[out] stats The controller's internal statistics + + @see PxControllerStats + */ + virtual void getStats(PxControllerStats& stats) const = 0; + + /** + \brief Resizes the controller. + + This function attempts to resize the controller to a given size, while making sure the bottom + position of the controller remains constant. In other words the function modifies both the + height and the (center) position of the controller. This is a helper function that can be used + to implement a 'crouch' functionality for example. + + \param[in] height Desired controller's height + */ + virtual void resize(PxReal height) = 0; + +protected: + PX_INLINE PxController() {} + virtual ~PxController() {} +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/characterkinematic/PxControllerBehavior.h b/sources/PhysX/PhysX/include/characterkinematic/PxControllerBehavior.h new file mode 100644 index 00000000..ea5ac3bb --- /dev/null +++ b/sources/PhysX/PhysX/include/characterkinematic/PxControllerBehavior.h @@ -0,0 +1,135 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_PHYSICS_CCT_BEHAVIOR +#define PX_PHYSICS_CCT_BEHAVIOR +/** \addtogroup character + @{ +*/ + +#include "PxFiltering.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + + class PxShape; + class PxObstacle; + class PxController; + + /** + \brief specifies controller behavior + */ + struct PxControllerBehaviorFlag + { + enum Enum + { + eCCT_CAN_RIDE_ON_OBJECT = (1<<0), //!< Controller can ride on touched object (i.e. when this touched object is moving horizontally). \note The CCT vs. CCT case is not supported. + eCCT_SLIDE = (1<<1), //!< Controller should slide on touched object + eCCT_USER_DEFINED_RIDE = (1<<2) //!< Disable all code dealing with controllers riding on objects, let users define it outside of the SDK. + }; + }; + + /** + \brief Bitfield that contains a set of raised flags defined in PxControllerBehaviorFlag. + + @see PxControllerBehaviorFlag + */ + typedef PxFlags PxControllerBehaviorFlags; + PX_FLAGS_OPERATORS(PxControllerBehaviorFlag::Enum, PxU8) + + /** + \brief User behavior callback. + + This behavior callback is called to customize the controller's behavior w.r.t. touched shapes. + */ + class PxControllerBehaviorCallback + { + public: + /** + \brief Retrieve behavior flags for a shape. + + When the CCT touches a shape, the CCT's behavior w.r.t. this shape can be customized by users. + This function retrieves the desired PxControllerBehaviorFlag flags capturing the desired behavior. + + \note See comments about deprecated functions at the start of this class + + \param[in] shape The shape the CCT is currently touching + \param[in] actor The actor owning the shape + + \return Desired behavior flags for the given shape + + @see PxControllerBehaviorFlag + */ + virtual PxControllerBehaviorFlags getBehaviorFlags(const PxShape& shape, const PxActor& actor) = 0; + + /** + \brief Retrieve behavior flags for a controller. + + When the CCT touches a controller, the CCT's behavior w.r.t. this controller can be customized by users. + This function retrieves the desired PxControllerBehaviorFlag flags capturing the desired behavior. + + \note The flag PxControllerBehaviorFlag::eCCT_CAN_RIDE_ON_OBJECT is not supported. + \note See comments about deprecated functions at the start of this class + + \param[in] controller The controller the CCT is currently touching + + \return Desired behavior flags for the given controller + + @see PxControllerBehaviorFlag + */ + virtual PxControllerBehaviorFlags getBehaviorFlags(const PxController& controller) = 0; + + /** + \brief Retrieve behavior flags for an obstacle. + + When the CCT touches an obstacle, the CCT's behavior w.r.t. this obstacle can be customized by users. + This function retrieves the desired PxControllerBehaviorFlag flags capturing the desired behavior. + + \note See comments about deprecated functions at the start of this class + + \param[in] obstacle The obstacle the CCT is currently touching + + \return Desired behavior flags for the given obstacle + + @see PxControllerBehaviorFlag + */ + virtual PxControllerBehaviorFlags getBehaviorFlags(const PxObstacle& obstacle) = 0; + + protected: + virtual ~PxControllerBehaviorCallback(){} + }; + +#if !PX_DOXYGEN +} +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/characterkinematic/PxControllerManager.h b/sources/PhysX/PhysX/include/characterkinematic/PxControllerManager.h new file mode 100644 index 00000000..8accda39 --- /dev/null +++ b/sources/PhysX/PhysX/include/characterkinematic/PxControllerManager.h @@ -0,0 +1,299 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_CCT_MANAGER +#define PX_PHYSICS_CCT_MANAGER +/** \addtogroup character + @{ +*/ + +#include "PxPhysXConfig.h" +#include "foundation/PxFlags.h" +#include "foundation/PxErrorCallback.h" +#include "common/PxRenderBuffer.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxPhysics; +class PxScene; +class PxController; +class PxControllerDesc; +class PxObstacleContext; +class PxControllerFilterCallback; + +/** +\brief specifies debug-rendering flags +*/ +struct PxControllerDebugRenderFlag +{ + enum Enum + { + eTEMPORAL_BV = (1<<0), //!< Temporal bounding volume around controllers + eCACHED_BV = (1<<1), //!< Cached bounding volume around controllers + eOBSTACLES = (1<<2), //!< User-defined obstacles + + eNONE = 0, + eALL = 0xffffffff + }; +}; + +/** +\brief Bitfield that contains a set of raised flags defined in PxControllerDebugRenderFlag. + +@see PxControllerDebugRenderFlag +*/ +typedef PxFlags PxControllerDebugRenderFlags; +PX_FLAGS_OPERATORS(PxControllerDebugRenderFlag::Enum, PxU32) + + +/** +\brief Manages an array of character controllers. + +@see PxController PxBoxController PxCapsuleController +*/ +class PxControllerManager +{ +public: + /** + \brief Releases the controller manager. + + \note This will release all associated controllers and obstacle contexts. + + \note This function is required to be called to release foundation usage. + + */ + virtual void release() = 0; + + /** + \brief Returns the scene the manager is adding the controllers to. + + \return The associated physics scene. + */ + virtual PxScene& getScene() const = 0; + + /** + \brief Returns the number of controllers that are being managed. + + \return The number of controllers. + */ + virtual PxU32 getNbControllers() const = 0; + + /** + \brief Retrieve one of the controllers in the manager. + + \param index the index of the controller to return + \return The controller with the specified index. + */ + virtual PxController* getController(PxU32 index) = 0; + + /** + \brief Creates a new character controller. + + \param[in] desc The controllers descriptor + \return The new controller + + @see PxController PxController.release() PxControllerDesc + */ + virtual PxController* createController(const PxControllerDesc& desc) = 0; + + /** + \brief Releases all the controllers that are being managed. + */ + virtual void purgeControllers() = 0; + + /** + \brief Retrieves debug data. + + \return The render buffer filled with debug-render data + + @see PxControllerManager.setDebugRenderingFlags() + */ + virtual PxRenderBuffer& getRenderBuffer() = 0; + + /** + \brief Sets debug rendering flags + + \param[in] flags The debug rendering flags (combination of PxControllerDebugRenderFlags) + + @see PxControllerManager.getRenderBuffer() PxControllerDebugRenderFlags + */ + virtual void setDebugRenderingFlags(PxControllerDebugRenderFlags flags) = 0; + + /** + \brief Returns the number of obstacle contexts that are being managed. + + \return The number of obstacle contexts. + */ + virtual PxU32 getNbObstacleContexts() const = 0; + + /** + \brief Retrieve one of the obstacle contexts in the manager. + + \param index The index of the obstacle context to retrieve. + \return The obstacle context with the specified index. + */ + virtual PxObstacleContext* getObstacleContext(PxU32 index) = 0; + + /** + \brief Creates an obstacle context. + + \return New obstacle context + + @see PxObstacleContext + */ + virtual PxObstacleContext* createObstacleContext() = 0; + + /** + \brief Computes character-character interactions. + + This function is an optional helper to properly resolve interactions between characters, in case they overlap (which can happen for gameplay reasons, etc). + + You should call this once per frame, before your PxController::move() calls. The function will not move the characters directly, but it will + compute overlap information for each character that will be used in the next move() call. + + You need to provide a proper time value here so that interactions are resolved in a way that do not depend on the framerate. + + If you only have one character in the scene, or if you can guarantee your characters will never overlap, then you do not need to call this function. + + \note Releasing the manager will automatically release all the associated obstacle contexts. + + \param[in] elapsedTime Elapsed time since last call + \param[in] cctFilterCb Filtering callback for CCT-vs-CCT interactions + */ + virtual void computeInteractions(PxF32 elapsedTime, PxControllerFilterCallback* cctFilterCb=NULL) = 0; + + /** + \brief Enables or disables runtime tessellation. + + Large triangles can create accuracy issues in the sweep code, which in turn can lead to characters not sliding smoothly + against geometries, or even penetrating them. This feature allows one to reduce those issues by tessellating large + triangles at runtime, before performing sweeps against them. The amount of tessellation is controlled by the 'maxEdgeLength' parameter. + Any triangle with at least one edge length greater than the maxEdgeLength will get recursively tessellated, until resulting triangles are small enough. + + This features only applies to triangle meshes, convex meshes, heightfields and boxes. + + \param[in] flag True/false to enable/disable runtime tessellation. + \param[in] maxEdgeLength Max edge length allowed before tessellation kicks in. + */ + virtual void setTessellation(bool flag, float maxEdgeLength) = 0; + + /** + \brief Enables or disables the overlap recovery module. + + The overlap recovery module can be used to depenetrate CCTs from static objects when an overlap is detected. This can happen + in three main cases: + - when the CCT is directly spawned or teleported in another object + - when the CCT algorithm fails due to limited FPU accuracy + - when the "up vector" is modified, making the rotated CCT shape overlap surrounding objects + + When activated, the CCT module will automatically try to resolve the penetration, and move the CCT to a safe place where it does + not overlap other objects anymore. This only concerns static objects, dynamic objects are ignored by the recovery module. + + When the recovery module is not activated, it is possible for the CCTs to go through static objects. By default, the recovery + module is enabled. + + The recovery module currently works with all geometries except heightfields. + + \param[in] flag True/false to enable/disable overlap recovery module. + */ + virtual void setOverlapRecoveryModule(bool flag) = 0; + + /** + \brief Enables or disables the precise sweeps. + + Precise sweeps are more accurate, but also potentially slower than regular sweeps. + + By default, precise sweeps are enabled. + + \param[in] flag True/false to enable/disable precise sweeps. + */ + virtual void setPreciseSweeps(bool flag) = 0; + + /** + \brief Enables or disables vertical sliding against ceilings. + + Geometry is seen as "ceilings" when the following condition is met: + + dot product(contact normal, up direction)<0.0f + + This flag controls whether characters should slide vertically along the geometry in that case. + + By default, sliding is allowed. + + \param[in] flag True/false to enable/disable sliding. + */ + virtual void setPreventVerticalSlidingAgainstCeiling(bool flag) = 0; + + /** + \brief Shift the origin of the character controllers and obstacle objects by the specified vector. + + The positions of all character controllers, obstacle objects and the corresponding data structures will get adjusted to reflect the shifted origin location + (the shift vector will get subtracted from all character controller and obstacle object positions). + + \note It is the user's responsibility to keep track of the summed total origin shift and adjust all input/output to/from PhysXCharacterKinematic accordingly. + + \note This call will not automatically shift the PhysX scene and its objects. You need to call PxScene::shiftOrigin() seperately to keep the systems in sync. + + \param[in] shift Translation vector to shift the origin by. + */ + virtual void shiftOrigin(const PxVec3& shift) = 0; + +protected: + PxControllerManager() {} + virtual ~PxControllerManager() {} +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + + /** + \brief Creates the controller manager. + + \param[in] scene PhysX scene. + \param[in] lockingEnabled Enables/disables internal locking. + + The character controller is informed by #PxDeletionListener::onRelease() when actors or shapes are released, and updates its internal + caches accordingly. If character controller movement or a call to #PxControllerManager::shiftOrigin() may overlap with actor/shape releases, + internal data structures must be guarded against concurrent access. + + Locking guarantees thread safety in such scenarios. + + \note locking may result in significant slowdown for release of actors or shapes. + + By default, locking is disabled. + */ +PX_C_EXPORT physx::PxControllerManager* PX_CALL_CONV PxCreateControllerManager(physx::PxScene& scene, bool lockingEnabled = false); + +/** @} */ +#endif //PX_PHYSICS_CCT_MANAGER diff --git a/sources/PhysX/PhysX/include/characterkinematic/PxControllerObstacles.h b/sources/PhysX/PhysX/include/characterkinematic/PxControllerObstacles.h new file mode 100644 index 00000000..b54a72cf --- /dev/null +++ b/sources/PhysX/PhysX/include/characterkinematic/PxControllerObstacles.h @@ -0,0 +1,191 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_PHYSICS_CCT_OBSTACLES +#define PX_PHYSICS_CCT_OBSTACLES +/** \addtogroup character + @{ +*/ + +#include "characterkinematic/PxExtended.h" +#include "geometry/PxGeometry.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + + class PxControllerManager; + + #define INVALID_OBSTACLE_HANDLE 0xffffffff + + /** + \brief Base class for obstacles. + + @see PxBoxObstacle PxCapsuleObstacle PxObstacleContext + */ + class PxObstacle + { + protected: + PxObstacle() : + mType (PxGeometryType::eINVALID), + mUserData (NULL), + mPos (0.0, 0.0, 0.0), + mRot (PxQuat(PxIdentity)) + {} + + PxGeometryType::Enum mType; + public: + + PX_FORCE_INLINE PxGeometryType::Enum getType() const { return mType; } + + void* mUserData; + PxExtendedVec3 mPos; + PxQuat mRot; + }; + + /** + \brief A box obstacle. + + @see PxObstacle PxCapsuleObstacle PxObstacleContext + */ + class PxBoxObstacle : public PxObstacle + { + public: + PxBoxObstacle() : + mHalfExtents(0.0f) + { mType = PxGeometryType::eBOX; } + + PxVec3 mHalfExtents; + }; + + /** + \brief A capsule obstacle. + + @see PxBoxObstacle PxObstacle PxObstacleContext + */ + class PxCapsuleObstacle : public PxObstacle + { + public: + PxCapsuleObstacle() : + mHalfHeight (0.0f), + mRadius (0.0f) + { mType = PxGeometryType::eCAPSULE; } + + PxReal mHalfHeight; + PxReal mRadius; + }; + + typedef PxU32 ObstacleHandle; + + /** + \brief Context class for obstacles. + + An obstacle context class contains and manages a set of user-defined obstacles. + + @see PxBoxObstacle PxCapsuleObstacle PxObstacle + */ + class PxObstacleContext + { + public: + PxObstacleContext() {} + virtual ~PxObstacleContext() {} + + /** + \brief Releases the context. + */ + virtual void release() = 0; + + /** + \brief Retrieves the controller manager associated with this context. + + \return The associated controller manager + */ + virtual PxControllerManager& getControllerManager() const = 0; + + /** + \brief Adds an obstacle to the context. + + \param [in] obstacle Obstacle data for the new obstacle. The data gets copied. + + \return Handle for newly-added obstacle + */ + virtual ObstacleHandle addObstacle(const PxObstacle& obstacle) = 0; + + /** + \brief Removes an obstacle from the context. + + \param [in] handle Handle for the obstacle object that needs to be removed. + + \return True if success + */ + virtual bool removeObstacle(ObstacleHandle handle) = 0; + + /** + \brief Updates data for an existing obstacle. + + \param [in] handle Handle for the obstacle object that needs to be updated. + \param [in] obstacle New obstacle data + + \return True if success + */ + virtual bool updateObstacle(ObstacleHandle handle, const PxObstacle& obstacle) = 0; + + /** + \brief Retrieves number of obstacles in the context. + + \return Number of obstacles in the context + */ + virtual PxU32 getNbObstacles() const = 0; + + /** + \brief Retrieves desired obstacle. + + \param [in] i Obstacle index + + \return Desired obstacle + */ + virtual const PxObstacle* getObstacle(PxU32 i) const = 0; + + /** + \brief Retrieves desired obstacle by given handle. + + \param [in] handle Obstacle handle + + \return Desired obstacle + */ + virtual const PxObstacle* getObstacleByHandle(ObstacleHandle handle) const = 0; + }; + +#if !PX_DOXYGEN +} +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/characterkinematic/PxExtended.h b/sources/PhysX/PhysX/include/characterkinematic/PxExtended.h new file mode 100644 index 00000000..6759c296 --- /dev/null +++ b/sources/PhysX/PhysX/include/characterkinematic/PxExtended.h @@ -0,0 +1,275 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_CCT_EXTENDED +#define PX_PHYSICS_CCT_EXTENDED +/** \addtogroup character + @{ +*/ + +// This needs to be included in Foundation just for the debug renderer + +#include "PxPhysXConfig.h" +#include "foundation/PxTransform.h" +#include "foundation/PxAssert.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +// This has to be done here since it also changes the top-level "Px" and "Np" APIs +#define PX_BIG_WORLDS + +#ifdef PX_BIG_WORLDS +typedef double PxExtended; +#define PX_MAX_EXTENDED PX_MAX_F64 +#define PxExtendedAbs(x) fabs(x) + +struct PxExtendedVec3 +{ + PX_INLINE PxExtendedVec3() {} + PX_INLINE PxExtendedVec3(PxExtended _x, PxExtended _y, PxExtended _z) : x(_x), y(_y), z(_z) {} + + PX_INLINE bool isZero() const + { + if(x!=0.0 || y!=0.0 || z!=0.0) return false; + return true; + } + + PX_INLINE PxExtended dot(const PxVec3& v) const + { + return x * PxExtended(v.x) + y * PxExtended(v.y) + z * PxExtended(v.z); + } + + PX_INLINE PxExtended distanceSquared(const PxExtendedVec3& v) const + { + PxExtended dx = x - v.x; + PxExtended dy = y - v.y; + PxExtended dz = z - v.z; + return dx * dx + dy * dy + dz * dz; + } + + PX_INLINE PxExtended magnitudeSquared() const + { + return x * x + y * y + z * z; + } + + PX_INLINE PxExtended magnitude() const + { + return PxSqrt(x * x + y * y + z * z); + } + + PX_INLINE PxExtended normalize() + { + PxExtended m = magnitude(); + if (m != 0.0) + { + const PxExtended il = PxExtended(1.0) / m; + x *= il; + y *= il; + z *= il; + } + return m; + } + + PX_INLINE bool isFinite() const + { + return PxIsFinite(x) && PxIsFinite(y) && PxIsFinite(z); + } + + PX_INLINE void maximum(const PxExtendedVec3& v) + { + if (x < v.x) x = v.x; + if (y < v.y) y = v.y; + if (z < v.z) z = v.z; + } + + + PX_INLINE void minimum(const PxExtendedVec3& v) + { + if (x > v.x) x = v.x; + if (y > v.y) y = v.y; + if (z > v.z) z = v.z; + } + + PX_INLINE void set(PxExtended x_, PxExtended y_, PxExtended z_) + { + this->x = x_; + this->y = y_; + this->z = z_; + } + + PX_INLINE void setPlusInfinity() + { + x = y = z = PX_MAX_EXTENDED; + } + + PX_INLINE void setMinusInfinity() + { + x = y = z = -PX_MAX_EXTENDED; + } + + PX_INLINE void cross(const PxExtendedVec3& left, const PxVec3& right) + { + // temps needed in case left or right is this. + PxExtended a = (left.y * PxExtended(right.z)) - (left.z * PxExtended(right.y)); + PxExtended b = (left.z * PxExtended(right.x)) - (left.x * PxExtended(right.z)); + PxExtended c = (left.x * PxExtended(right.y)) - (left.y * PxExtended(right.x)); + + x = a; + y = b; + z = c; + } + + PX_INLINE void cross(const PxExtendedVec3& left, const PxExtendedVec3& right) + { + // temps needed in case left or right is this. + PxExtended a = (left.y * right.z) - (left.z * right.y); + PxExtended b = (left.z * right.x) - (left.x * right.z); + PxExtended c = (left.x * right.y) - (left.y * right.x); + + x = a; + y = b; + z = c; + } + + PX_INLINE PxExtendedVec3 cross(const PxExtendedVec3& v) const + { + PxExtendedVec3 temp; + temp.cross(*this,v); + return temp; + } + + PX_INLINE void cross(const PxVec3& left, const PxExtendedVec3& right) + { + // temps needed in case left or right is this. + PxExtended a = (PxExtended(left.y) * right.z) - (PxExtended(left.z) * right.y); + PxExtended b = (PxExtended(left.z) * right.x) - (PxExtended(left.x) * right.z); + PxExtended c = (PxExtended(left.x) * right.y) - (PxExtended(left.y) * right.x); + + x = a; + y = b; + z = c; + } + + PX_INLINE PxExtendedVec3 operator-() const + { + return PxExtendedVec3(-x, -y, -z); + } + + PX_INLINE PxExtendedVec3& operator+=(const PxExtendedVec3& v) + { + x += v.x; + y += v.y; + z += v.z; + return *this; + } + + PX_INLINE PxExtendedVec3& operator-=(const PxExtendedVec3& v) + { + x -= v.x; + y -= v.y; + z -= v.z; + return *this; + } + + PX_INLINE PxExtendedVec3& operator+=(const PxVec3& v) + { + x += PxExtended(v.x); + y += PxExtended(v.y); + z += PxExtended(v.z); + return *this; + } + + PX_INLINE PxExtendedVec3& operator-=(const PxVec3& v) + { + x -= PxExtended(v.x); + y -= PxExtended(v.y); + z -= PxExtended(v.z); + return *this; + } + + PX_INLINE PxExtendedVec3& operator*=(const PxReal& s) + { + x *= PxExtended(s); + y *= PxExtended(s); + z *= PxExtended(s); + return *this; + } + + PX_INLINE PxExtendedVec3 operator+(const PxExtendedVec3& v) const + { + return PxExtendedVec3(x + v.x, y + v.y, z + v.z); + } + + PX_INLINE PxVec3 operator-(const PxExtendedVec3& v) const + { + return PxVec3(PxReal(x - v.x), PxReal(y - v.y), PxReal(z - v.z)); + } + + PX_INLINE PxExtended& operator[](int index) + { + PX_ASSERT(index>=0 && index<=2); + + return reinterpret_cast(this)[index]; + } + + + PX_INLINE PxExtended operator[](int index) const + { + PX_ASSERT(index>=0 && index<=2); + + return reinterpret_cast(this)[index]; + } + + PxExtended x,y,z; +}; + + PX_FORCE_INLINE PxVec3 toVec3(const PxExtendedVec3& v) + { + return PxVec3(float(v.x), float(v.y), float(v.z)); + } + +#else +// Big worlds not defined + +typedef PxVec3 PxExtendedVec3; +typedef PxReal PxExtended; +#define PX_MAX_EXTENDED PX_MAX_F32 +#define PxExtendedAbs(x) fabsf(x) +#endif + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/collision/PxCollisionDefs.h b/sources/PhysX/PhysX/include/collision/PxCollisionDefs.h new file mode 100644 index 00000000..5923d095 --- /dev/null +++ b/sources/PhysX/PhysX/include/collision/PxCollisionDefs.h @@ -0,0 +1,87 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_COLLISION_DEFS_H +#define PX_COLLISION_DEFS_H + +#include "PxPhysXConfig.h" +#include "foundation/PxVec3.h" +#include "foundation/PxMat33.h" +#include "geomutils/GuContactPoint.h" +#include "geomutils/GuContactBuffer.h" +#include "geometry/PxGeometry.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + + /** + \brief A structure to cache contact information produced by LL contact gen functions. + */ + struct PxCache + { + PxU8* mCachedData; //!< Cached data pointer. Allocated via PxCacheAllocator + PxU16 mCachedSize; //!< The total size of the cached data + PxU8 mPairData; //!< Pair data information used and cached internally by some contact gen functions to accelerate performance. + PxU8 mManifoldFlags; //!< Manifold flags used to identify the format the cached data is stored in. + + PX_FORCE_INLINE PxCache() : mCachedData(NULL), mCachedSize(0), mPairData(0), mManifoldFlags(0) + { + } + + PX_FORCE_INLINE void reset() { mCachedData = NULL; mCachedSize = 0; mPairData = 0; mManifoldFlags = 0;} + }; + + + /** + A callback class to allocate memory to cache information used in contact generation. + */ + class PxCacheAllocator + { + public: + /** + \brief Allocates cache data for contact generation. This data is stored inside PxCache objects. The application can retain and provide this information for future contact generation passes + for a given pair to improve contact generation performance. It is the application's responsibility to release this memory appropriately. If the memory is released, the application must ensure that + this memory is no longer referenced by any PxCache objects passed to PxGenerateContacts. + \param byteSize The size of the allocation in bytes + \return the newly-allocated memory. The returned address must be 16-byte aligned. + */ + virtual PxU8* allocateCacheData(const PxU32 byteSize) = 0; + + virtual ~PxCacheAllocator() {} + }; + +#if !PX_DOXYGEN +} +#endif + +#endif + diff --git a/sources/PhysX/PhysX/include/common/PxBase.h b/sources/PhysX/PhysX/include/common/PxBase.h new file mode 100644 index 00000000..cc4f8797 --- /dev/null +++ b/sources/PhysX/PhysX/include/common/PxBase.h @@ -0,0 +1,201 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_PX_BASE +#define PX_PHYSICS_PX_BASE + +/** \addtogroup common +@{ +*/ + +#include "foundation/PxFlags.h" +#include "common/PxSerialFramework.h" +#include "common/PxCollection.h" +#include "common/PxTypeInfo.h" +#include // For strcmp + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +typedef PxU16 PxType; + +/** +\brief Flags for PxBase. +*/ +struct PxBaseFlag +{ + enum Enum + { + eOWNS_MEMORY = (1<<0), + eIS_RELEASABLE = (1<<1) + }; +}; + +typedef PxFlags PxBaseFlags; +PX_FLAGS_OPERATORS(PxBaseFlag::Enum, PxU16) + +/** +\brief Base class for objects that can be members of a PxCollection. + +All PxBase sub-classes can be serialized. + +@see PxCollection +*/ +class PxBase +{ +//= ATTENTION! ===================================================================================== +// Changing the data layout of this class breaks the binary serialization format. See comments for +// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData +// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION +// accordingly. +//================================================================================================== +public: + /** + \brief Releases the PxBase instance, please check documentation of release in derived class. + */ + virtual void release() = 0; + + /** + \brief Returns string name of dynamic type. + \return Class name of most derived type of this object. + */ + virtual const char* getConcreteTypeName() const = 0; + + /* brief Implements dynamic cast functionality. + + Example use: + + if(actor->is()) {...} + + \return A pointer to the specified type if object matches, otherwise NULL + */ + template T* is() { return typeMatch() ? static_cast(this) : NULL; } + + /* brief Implements dynamic cast functionality for const objects. + + Example use: + + if(actor->is()) {...} + + \return A pointer to the specified type if object matches, otherwise NULL + */ + template const T* is() const { return typeMatch() ? static_cast(this) : NULL; } + + /** + \brief Returns concrete type of object. + \return PxConcreteType::Enum of serialized object + + @see PxConcreteType + */ + PX_FORCE_INLINE PxType getConcreteType() const { return mConcreteType; } + + /** + \brief Set PxBaseFlag + + \param[in] flag The flag to be set + \param[in] value The flags new value + */ + PX_FORCE_INLINE void setBaseFlag(PxBaseFlag::Enum flag, bool value) { mBaseFlags = value ? mBaseFlags|flag : mBaseFlags&~flag; } + + /** + \brief Set PxBaseFlags + + \param[in] inFlags The flags to be set + + @see PxBaseFlags + */ + PX_FORCE_INLINE void setBaseFlags(PxBaseFlags inFlags) { mBaseFlags = inFlags; } + + /** + \brief Returns PxBaseFlags + + \return PxBaseFlags + + @see PxBaseFlags + */ + PX_FORCE_INLINE PxBaseFlags getBaseFlags() const { return mBaseFlags; } + + /** + \brief Whether the object is subordinate. + + A class is subordinate, if it can only be instantiated in the context of another class. + + \return Whether the class is subordinate + + @see PxSerialization::isSerializable + */ + virtual bool isReleasable() const { return mBaseFlags & PxBaseFlag::eIS_RELEASABLE; } + +protected: + /** + \brief Constructor setting concrete type and base flags. + */ + PX_INLINE PxBase(PxType concreteType, PxBaseFlags baseFlags) + : mConcreteType(concreteType), mBaseFlags(baseFlags) {} + + /** + \brief Deserialization constructor setting base flags. + */ + PX_INLINE PxBase(PxBaseFlags baseFlags) : mBaseFlags(baseFlags) {} + + /** + \brief Destructor. + */ + virtual ~PxBase() {} + + /** + \brief Returns whether a given type name matches with the type of this instance + */ + virtual bool isKindOf(const char* superClass) const { return !::strcmp(superClass, "PxBase"); } + + template bool typeMatch() const + { + return PxU32(PxTypeInfo::eFastTypeId)!=PxU32(PxConcreteType::eUNDEFINED) ? + PxU32(getConcreteType()) == PxU32(PxTypeInfo::eFastTypeId) : isKindOf(PxTypeInfo::name()); + } + + +private: + friend void getBinaryMetaData_PxBase(PxOutputStream& stream); + +protected: + PxType mConcreteType; // concrete type identifier - see PxConcreteType. + PxBaseFlags mBaseFlags; // internal flags + +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/common/PxCollection.h b/sources/PhysX/PhysX/include/common/PxCollection.h new file mode 100644 index 00000000..d9ec5cfc --- /dev/null +++ b/sources/PhysX/PhysX/include/common/PxCollection.h @@ -0,0 +1,279 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_PX_COLLECTION +#define PX_PHYSICS_PX_COLLECTION + +#include "common/PxSerialFramework.h" + +/** \addtogroup common +@{ +*/ + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxBase; + +/** +\brief Collection class for serialization. + +A collection is a set of PxBase objects. PxBase objects can be added to the collection +regardless of other objects they depend on. Objects may be named using PxSerialObjectId values in order +to resolve dependencies between objects of different collections. + +Serialization and deserialization only work through collections. + +A scene is typically serialized using the following steps: + + -# create a serialization registry + -# create a collection for scene objects + -# complete the scene objects (adds all dependent objects, e.g. meshes) + -# serialize collection + -# release collection + -# release serialization registry + +For example the code may look like this: + +\code + PxPhysics* physics; // The physics + PxScene* scene; // The physics scene + SerialStream s; // The user-defined stream doing the actual write to disk + + PxSerializationRegistry* registry = PxSerialization::createSerializationRegistry(*physics); // step 1) + PxCollection* collection = PxSerialization::createCollection(*scene); // step 2) + PxSerialization::complete(*collection, *registry); // step 3) + PxSerialization::serializeCollectionToBinary(s, *collection, *registry); // step 4) + collection->release(); // step 5) + registry->release(); // step 6) +\endcode + +A scene is typically deserialized using the following steps: + + -# load a serialized collection into memory + -# create a serialization registry + -# create a collection by passing the serialized memory block + -# add collected objects to scene + -# release collection + -# release serialization registry + +For example the code may look like this: + +\code + PxPhysics* physics; // The physics + PxScene* scene; // The physics scene + void* memory128; // a 128-byte aligned buffer previously loaded from disk by the user - step 1) + + PxSerializationRegistry* registry = PxSerialization::createSerializationRegistry(*physics); // step 2) + PxCollection* collection = PxSerialization::createCollectionFromBinary(memory128, *registry); // step 3) + scene->addCollection(*collection); // step 4) + collection->release(); // step 5) + registry->release(); // step 6) +\endcode + +@see PxBase, PxCreateCollection() +*/ +class PxCollection +{ +public: + + /** + \brief Adds a PxBase object to the collection. + + Adds a PxBase object to the collection. Optionally a PxSerialObjectId can be provided + in order to resolve dependencies between collections. A PxSerialObjectId value of PX_SERIAL_OBJECT_ID_INVALID + means the object remains without id. Objects can be added regardless of other objects they require. If the object + is already in the collection, the ID will be set if it was PX_SERIAL_OBJECT_ID_INVALID previously, otherwise the + operation fails. + + + \param[in] object Object to be added to the collection + \param[in] id Optional PxSerialObjectId id + */ + virtual void add(PxBase& object, PxSerialObjectId id = PX_SERIAL_OBJECT_ID_INVALID) = 0; + + /** + \brief Removes a PxBase member object from the collection. + + Object needs to be contained by the collection. + + \param[in] object PxBase object to be removed + */ + virtual void remove(PxBase& object) = 0; + + /** + \brief Returns whether the collection contains a certain PxBase object. + + \param[in] object PxBase object + \return Whether object is contained. + */ + virtual bool contains(PxBase& object) const = 0; + + /** + \brief Adds an id to a member PxBase object. + + If the object is already associated with an id within the collection, the id is replaced. + May only be called for objects that are members of the collection. The id needs to be unique + within the collection. + + \param[in] object Member PxBase object + \param[in] id PxSerialObjectId id to be given to the object + */ + virtual void addId(PxBase& object, PxSerialObjectId id) = 0; + + /** + \brief Removes id from a contained PxBase object. + + May only be called for ids that are associated with an object in the collection. + + \param[in] id PxSerialObjectId value + */ + virtual void removeId(PxSerialObjectId id) = 0; + + /** + \brief Adds all PxBase objects and their ids of collection to this collection. + + PxBase objects already in this collection are ignored. Object ids need to be conflict + free, i.e. the same object may not have two different ids within the two collections. + + \param[in] collection Collection to be added + */ + virtual void add(PxCollection& collection) = 0; + + /** + \brief Removes all PxBase objects of collection from this collection. + + PxBase objects not present in this collection are ignored. Ids of objects + which are removed are also removed. + + \param[in] collection Collection to be removed + */ + virtual void remove(PxCollection& collection) = 0; + + /** + \brief Gets number of PxBase objects in this collection. + + \return Number of objects in this collection + */ + virtual PxU32 getNbObjects() const = 0; + + /** + \brief Gets the PxBase object of this collection given its index. + + \param[in] index PxBase index in [0, getNbObjects()) + \return PxBase object at index index + */ + virtual PxBase& getObject(PxU32 index) const = 0; + + /** + \brief Copies member PxBase pointers to a user specified buffer. + + \param[out] userBuffer Array of PxBase pointers + \param[in] bufferSize Capacity of userBuffer + \param[in] startIndex Offset into list of member PxBase objects + \return number of members PxBase objects that have been written to the userBuffer + */ + virtual PxU32 getObjects(PxBase** userBuffer, PxU32 bufferSize, PxU32 startIndex=0) const = 0; + + /** + \brief Looks for a PxBase object given a PxSerialObjectId value. + + If there is no PxBase object in the collection with the given id, NULL is returned. + + \param[in] id PxSerialObjectId value to look for + \return PxBase object with the given id value or NULL + */ + virtual PxBase* find(PxSerialObjectId id) const = 0; + + /** + \brief Gets number of PxSerialObjectId names in this collection. + + \return Number of PxSerialObjectId names in this collection + */ + virtual PxU32 getNbIds() const = 0; + + /** + \brief Copies member PxSerialObjectId values to a user specified buffer. + + \param[out] userBuffer Array of PxSerialObjectId values + \param[in] bufferSize Capacity of userBuffer + \param[in] startIndex Offset into list of member PxSerialObjectId values + \return number of members PxSerialObjectId values that have been written to the userBuffer + */ + virtual PxU32 getIds(PxSerialObjectId* userBuffer, PxU32 bufferSize, PxU32 startIndex=0) const = 0; + + /** + \brief Gets the PxSerialObjectId name of a PxBase object within the collection. + + The PxBase object needs to be a member of the collection. + + \param[in] object PxBase object to get id for + \return PxSerialObjectId name of the object or PX_SERIAL_OBJECT_ID_INVALID if the object is unnamed + */ + virtual PxSerialObjectId getId(const PxBase& object) const = 0; + + /** + \brief Deletes a collection object. + + This function only deletes the collection object, i.e. the container class. It doesn't delete objects + that are part of the collection. + + @see PxCreateCollection() + */ + + virtual void release() = 0; + +protected: + PxCollection() {} + virtual ~PxCollection() {} +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** +\brief Creates a collection object. + +Objects can only be serialized or deserialized through a collection. +For serialization, users must add objects to the collection and serialize the collection as a whole. +For deserialization, the system gives back a collection of deserialized objects to users. + +\return The new collection object. + +@see PxCollection, PxCollection::release() +*/ +PX_PHYSX_COMMON_API physx::PxCollection* PX_CALL_CONV PxCreateCollection(); + + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/common/PxCoreUtilityTypes.h b/sources/PhysX/PhysX/include/common/PxCoreUtilityTypes.h new file mode 100644 index 00000000..0c4d4809 --- /dev/null +++ b/sources/PhysX/PhysX/include/common/PxCoreUtilityTypes.h @@ -0,0 +1,211 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_CORE_UTILTY_TYPES_H +#define PX_CORE_UTILTY_TYPES_H +/** \addtogroup common +@{ +*/ + +#include "foundation/PxAssert.h" +#include "foundation/PxMemory.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + + +struct PxStridedData +{ + /** + \brief The offset in bytes between consecutive samples in the data. + + Default: 0 + */ + PxU32 stride; + const void* data; + + PxStridedData() : stride( 0 ), data( NULL ) {} + + template + PX_INLINE const TDataType& at( PxU32 idx ) const + { + PxU32 theStride( stride ); + if ( theStride == 0 ) + theStride = sizeof( TDataType ); + PxU32 offset( theStride * idx ); + return *(reinterpret_cast( reinterpret_cast< const PxU8* >( data ) + offset )); + } +}; + +template +struct PxTypedStridedData +{ + PxU32 stride; + const TDataType* data; + + PxTypedStridedData() + : stride( 0 ) + , data( NULL ) + { + } + +}; + +struct PxBoundedData : public PxStridedData +{ + PxU32 count; + PxBoundedData() : count( 0 ) {} +}; + +template +struct PxPadding +{ + PxU8 mPadding[TNumBytes]; + PxPadding() + { + for ( PxU8 idx =0; idx < TNumBytes; ++idx ) + mPadding[idx] = 0; + } +}; + +template class PxFixedSizeLookupTable +{ +//= ATTENTION! ===================================================================================== +// Changing the data layout of this class breaks the binary serialization format. See comments for +// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData +// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION +// accordingly. +//================================================================================================== +public: + + PxFixedSizeLookupTable() + : mNbDataPairs(0) + { + } + + PxFixedSizeLookupTable(const PxEMPTY) {} + + PxFixedSizeLookupTable(const PxReal* dataPairs, const PxU32 numDataPairs) + { + PxMemCopy(mDataPairs,dataPairs,sizeof(PxReal)*2*numDataPairs); + mNbDataPairs=numDataPairs; + } + + PxFixedSizeLookupTable(const PxFixedSizeLookupTable& src) + { + PxMemCopy(mDataPairs,src.mDataPairs,sizeof(PxReal)*2*src.mNbDataPairs); + mNbDataPairs=src.mNbDataPairs; + } + + ~PxFixedSizeLookupTable() + { + } + + PxFixedSizeLookupTable& operator=(const PxFixedSizeLookupTable& src) + { + PxMemCopy(mDataPairs,src.mDataPairs,sizeof(PxReal)*2*src.mNbDataPairs); + mNbDataPairs=src.mNbDataPairs; + return *this; + } + + PX_FORCE_INLINE void addPair(const PxReal x, const PxReal y) + { + PX_ASSERT(mNbDataPairs=x0)&&(x=getX(mNbDataPairs-1)); + return getY(mNbDataPairs-1); + } + + PxU32 getNbDataPairs() const {return mNbDataPairs;} + + void clear() + { + memset(mDataPairs, 0, NB_ELEMENTS*2*sizeof(PxReal)); + mNbDataPairs = 0; + } + + PX_FORCE_INLINE PxReal getX(const PxU32 i) const + { + return mDataPairs[2*i]; + } + PX_FORCE_INLINE PxReal getY(const PxU32 i) const + { + return mDataPairs[2*i+1]; + } + + PxReal mDataPairs[2*NB_ELEMENTS]; + PxU32 mNbDataPairs; + PxU32 mPad[3]; + + +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/common/PxMetaData.h b/sources/PhysX/PhysX/include/common/PxMetaData.h new file mode 100644 index 00000000..27c06d4b --- /dev/null +++ b/sources/PhysX/PhysX/include/common/PxMetaData.h @@ -0,0 +1,228 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_METADATA_H +#define PX_PHYSICS_METADATA_H +/** \addtogroup physics +@{ +*/ + +#include "foundation/Px.h" +#include "foundation/PxIO.h" +#include "PxMetaDataFlags.h" + + +#if !PX_DOXYGEN +namespace physx +{ +#endif + + /** + \brief Struct to store meta data definitions. + + Note: The individual fields have different meaning depending on the meta data entry configuration. + */ + struct PxMetaDataEntry + { + const char* type; //!< Field type (bool, byte, quaternion, etc) + const char* name; //!< Field name (appears exactly as in the source file) + PxU32 offset; //!< Offset from the start of the class (ie from "this", field is located at "this"+Offset) + PxU32 size; //!< sizeof(Type) + PxU32 count; //!< Number of items of type Type (0 for dynamic sizes) + PxU32 offsetSize; //!< Offset of dynamic size param, for dynamic arrays + PxU32 flags; //!< Field parameters + PxU32 alignment; //!< Explicit alignment + }; + + #define PX_STORE_METADATA(stream, metaData) stream.write(&metaData, sizeof(PxMetaDataEntry)) + + #define PX_SIZE_OF(Class, Member) sizeof((reinterpret_cast(0))->Member) + + /** + \brief specifies a binary metadata entry for a member variable of a class + */ + #define PX_DEF_BIN_METADATA_ITEM(stream, Class, type, name, flags) \ + { \ + PxMetaDataEntry tmp = { #type, #name, PxU32(PX_OFFSET_OF_RT(Class, name)), PX_SIZE_OF(Class, name), \ + 1, 0, flags, 0}; \ + PX_STORE_METADATA(stream, tmp); \ + } + + /** + \brief specifies a binary metadata entry for a member array variable of a class + \details similar to PX_DEF_BIN_METADATA_ITEMS_AUTO but for cases with mismatch between specified type and array type + */ + #define PX_DEF_BIN_METADATA_ITEMS(stream, Class, type, name, flags, count) \ + { \ + PxMetaDataEntry tmp = { #type, #name, PxU32(PX_OFFSET_OF_RT(Class, name)), PX_SIZE_OF(Class, name), \ + count, 0, flags, 0}; \ + PX_STORE_METADATA(stream, tmp); \ + } + + /** + \brief specifies a binary metadata entry for a member array variable of a class + \details similar to PX_DEF_BIN_METADATA_ITEMS but automatically detects the array length, which only works when the specified + type matches the type of the array - does not support PxMetaDataFlag::ePTR + */ + #define PX_DEF_BIN_METADATA_ITEMS_AUTO(stream, Class, type, name, flags) \ + { \ + PxMetaDataEntry tmp = { #type, #name, PxU32(PX_OFFSET_OF_RT(Class, name)), PX_SIZE_OF(Class, name), \ + sizeof((reinterpret_cast(0))->name)/sizeof(type), 0, flags, 0}; \ + PX_STORE_METADATA(stream, tmp); \ + } + + /** + \brief specifies a binary metadata entry for a class + */ + #define PX_DEF_BIN_METADATA_CLASS(stream, Class) \ + { \ + PxMetaDataEntry tmp = { #Class, 0, 0, sizeof(Class), 0, 0, PxMetaDataFlag::eCLASS, 0 }; \ + PX_STORE_METADATA(stream, tmp); \ + } + + /** + \brief specifies a binary metadata entry for a virtual class + */ + #define PX_DEF_BIN_METADATA_VCLASS(stream, Class) \ + { \ + PxMetaDataEntry tmp = { #Class, 0, 0, sizeof(Class), 0, 0, PxMetaDataFlag::eCLASS|PxMetaDataFlag::eVIRTUAL, 0}; \ + PX_STORE_METADATA(stream, tmp); \ + } + + /** + \brief specifies a binary metadata entry for a typedef + */ + #define PX_DEF_BIN_METADATA_TYPEDEF(stream, newType, oldType) \ + { \ + PxMetaDataEntry tmp = { #newType, #oldType, 0, 0, 0, 0, PxMetaDataFlag::eTYPEDEF, 0 }; \ + PX_STORE_METADATA(stream, tmp); \ + } + + /** + \brief specifies a binary metadata entry for declaring a base class + */ + #define PX_DEF_BIN_METADATA_BASE_CLASS(stream, Class, BaseClass) \ + { \ + Class* myClass = reinterpret_cast(42); \ + BaseClass* s = static_cast(myClass); \ + const PxU32 offset = PxU32(size_t(s) - size_t(myClass)); \ + PxMetaDataEntry tmp = { #Class, #BaseClass, offset, sizeof(Class), 0, 0, PxMetaDataFlag::eCLASS, 0 }; \ + PX_STORE_METADATA(stream, tmp); \ + } + + /** + \brief specifies a binary metadata entry for a union + */ + #define PX_DEF_BIN_METADATA_UNION(stream, Class, name) \ + { \ + PxMetaDataEntry tmp = { #Class, 0, PxU32(PX_OFFSET_OF_RT(Class, name)), PX_SIZE_OF(Class, name), \ + 1, 0, PxMetaDataFlag::eUNION, 0 }; \ + PX_STORE_METADATA(stream, tmp); \ + } + + /** + \brief specifies a binary metadata entry for a particular member type of a union + */ + #define PX_DEF_BIN_METADATA_UNION_TYPE(stream, Class, type, enumValue) \ + { \ + PxMetaDataEntry tmp = { #Class, #type, enumValue, 0, 0, 0, PxMetaDataFlag::eUNION, 0 }; \ + PX_STORE_METADATA(stream, tmp); \ + } + + /** + \brief specifies a binary metadata entry for extra data + */ + #define PX_DEF_BIN_METADATA_EXTRA_ITEM(stream, Class, type, control, align) \ + { \ + PxMetaDataEntry tmp = { #type, 0, PxU32(PX_OFFSET_OF_RT(Class, control)), sizeof(type), 0, PxU32(PX_SIZE_OF(Class, control)), \ + PxMetaDataFlag::eEXTRA_DATA|PxMetaDataFlag::eEXTRA_ITEM, align }; \ + PX_STORE_METADATA(stream, tmp); \ + } + + /** + \brief specifies a binary metadata entry for an array of extra data + */ + #define PX_DEF_BIN_METADATA_EXTRA_ITEMS(stream, Class, type, control, count, flags, align) \ + { \ + PxMetaDataEntry tmp = { #type, 0, PxU32(PX_OFFSET_OF_RT(Class, control)), PxU32(PX_SIZE_OF(Class, control)), \ + PxU32(PX_OFFSET_OF_RT(Class, count)), PxU32(PX_SIZE_OF(Class, count)), \ + PxMetaDataFlag::eEXTRA_DATA|PxMetaDataFlag::eEXTRA_ITEMS|flags, align }; \ + PX_STORE_METADATA(stream, tmp); \ + } + + /** + \brief specifies a binary metadata entry for an array of extra data + additional to PX_DEF_BIN_METADATA_EXTRA_ITEMS a mask can be specified to interpret the control value + @see PxMetaDataFlag::eCONTROL_MASK + */ + #define PX_DEF_BIN_METADATA_EXTRA_ITEMS_MASKED_CONTROL(stream, Class, type, control, controlMask ,count, flags, align) \ + { \ + PxMetaDataEntry tmp = { #type, 0, PxU32(PX_OFFSET_OF_RT(Class, control)), PxU32(PX_SIZE_OF(Class, control)), \ + PxU32(PX_OFFSET_OF_RT(Class, count)), PxU32(PX_SIZE_OF(Class, count)), \ + PxMetaDataFlag::eCONTROL_MASK|PxMetaDataFlag::eEXTRA_DATA|PxMetaDataFlag::eEXTRA_ITEMS|flags|(controlMask & PxMetaDataFlag::eCONTROL_MASK_RANGE) << 16, \ + align}; \ + PX_STORE_METADATA(stream, tmp); \ + } + + /** + \brief specifies a binary metadata entry for an array of extra data + \details similar to PX_DEF_BIN_METADATA_EXTRA_ITEMS, but supporting no control - PxMetaDataFlag::ePTR is also not supported + */ + #define PX_DEF_BIN_METADATA_EXTRA_ARRAY(stream, Class, type, dyn_count, align, flags) \ + { \ + PxMetaDataEntry tmp = { #type, 0, PxU32(PX_OFFSET_OF_RT(Class, dyn_count)), PX_SIZE_OF(Class, dyn_count), align, 0, \ + PxMetaDataFlag::eEXTRA_DATA|flags, align }; \ + PX_STORE_METADATA(stream, tmp); \ + } + + /** + \brief specifies a binary metadata entry for an string of extra data + */ + #define PX_DEF_BIN_METADATA_EXTRA_NAME(stream, Class, control, align) \ + { \ + PxMetaDataEntry tmp = { "char", "string", 0, 0, 0, 0, PxMetaDataFlag::eEXTRA_DATA|PxMetaDataFlag::eEXTRA_NAME, align }; \ + PX_STORE_METADATA(stream, tmp); \ + } + + /** + \brief specifies a binary metadata entry declaring an extra data alignment for a class + */ + #define PX_DEF_BIN_METADATA_EXTRA_ALIGN(stream, Class, align) \ + { \ + PxMetaDataEntry tmp = { "PxU8", "Alignment", 0, 0, 0, 0, PxMetaDataFlag::eEXTRA_DATA|PxMetaDataFlag::eALIGNMENT, align}; \ + PX_STORE_METADATA(stream, tmp); \ + } + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/common/PxMetaDataFlags.h b/sources/PhysX/PhysX/include/common/PxMetaDataFlags.h new file mode 100644 index 00000000..c8718e74 --- /dev/null +++ b/sources/PhysX/PhysX/include/common/PxMetaDataFlags.h @@ -0,0 +1,75 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_METADATA_FLAGS +#define PX_PHYSICS_METADATA_FLAGS + +#include "foundation/Px.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + + /** + \brief Flags used to configure binary meta data entries, typically set through PX_DEF_BIN_METADATA defines. + + @see PxMetaDataEntry + */ + struct PxMetaDataFlag + { + enum Enum + { + eCLASS = (1<<0), //!< declares a class + eVIRTUAL = (1<<1), //!< declares class to be virtual + eTYPEDEF = (1<<2), //!< declares a typedef + ePTR = (1<<3), //!< declares a pointer + eHANDLE = (1<<4), //!< declares a handle + eEXTRA_DATA = (1<<5), //!< declares extra data exported with PxSerializer::exportExtraData + eEXTRA_ITEM = (1<<6), //!< specifies one element of extra data + eEXTRA_ITEMS = (1<<7), //!< specifies an array of extra data + eEXTRA_NAME = (1<<8), //!< specifies a name of extra data + eUNION = (1<<9), //!< declares a union + ePADDING = (1<<10), //!< declares explicit padding data + eALIGNMENT = (1<<11), //!< declares aligned data + eCOUNT_MASK_MSB = (1<<12), //!< specifies that the count value's most significant bit needs to be masked out + eCOUNT_SKIP_IF_ONE = (1<<13), //!< specifies that the count value is treated as zero for a variable value of one - special case for single triangle meshes + eCONTROL_FLIP = (1<<14), //!< specifies that the control value is the negate of the variable value + eCONTROL_MASK = (1<<15), //!< specifies that the control value is masked - mask bits are assumed to be within eCONTROL_MASK_RANGE + eCONTROL_MASK_RANGE = 0x000000FF, //!< mask range allowed for eCONTROL_MASK + eFORCE_DWORD = 0x7fffffff + }; + }; + +#if !PX_DOXYGEN +} +#endif + +#endif diff --git a/sources/PhysX/PhysX/include/common/PxPhysXCommonConfig.h b/sources/PhysX/PhysX/include/common/PxPhysXCommonConfig.h new file mode 100644 index 00000000..d2f83a0d --- /dev/null +++ b/sources/PhysX/PhysX/include/common/PxPhysXCommonConfig.h @@ -0,0 +1,124 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_COMMON_NX +#define PX_PHYSICS_COMMON_NX + +/** \addtogroup common +@{ */ + +#include "foundation/Px.h" + +/*Disable support for VS2017 prior version 15.5.1 for windows platform, because of a compiler bug: +https://developercommunity.visualstudio.com/content/problem/66047/possible-compiler-bug.html +*/ +#if (PX_VC == 15) && PX_WINDOWS && (_MSC_FULL_VER < 191225830) +#error Visual studio 2017 prior to 15.5.1 is not supported because of a compiler bug. +#endif + +// define API function declaration (public API only needed because of extensions) +#if defined PX_PHYSX_STATIC_LIB + #define PX_PHYSX_CORE_API +#else + #if (PX_WINDOWS_FAMILY || PX_XBOXONE || PX_PS4) + #if defined PX_PHYSX_CORE_EXPORTS + #define PX_PHYSX_CORE_API __declspec(dllexport) + #else + #define PX_PHYSX_CORE_API __declspec(dllimport) + #endif + #elif PX_UNIX_FAMILY + #define PX_PHYSX_CORE_API PX_UNIX_EXPORT + #else + #define PX_PHYSX_CORE_API + #endif +#endif + +#if PX_SUPPORT_GPU_PHYSX +// define API function declaration +#if defined PX_PHYSX_GPU_STATIC + #define PX_PHYSX_GPU_API +#else + #if PX_WINDOWS + #if defined PX_PHYSX_GPU_EXPORTS + #define PX_PHYSX_GPU_API __declspec(dllexport) + #else + #define PX_PHYSX_GPU_API __declspec(dllimport) + #endif + #elif PX_UNIX_FAMILY + #define PX_PHYSX_GPU_API PX_UNIX_EXPORT + #else + #define PX_PHYSX_GPU_API + #endif +#endif + +#else // PX_SUPPORT_GPU_PHYSX +#define PX_PHYSX_GPU_API +#endif // PX_SUPPORT_GPU_PHYSX + +#if defined PX_PHYSX_STATIC_LIB + #define PX_PHYSX_COMMON_API +#else + #if (PX_WINDOWS_FAMILY || PX_XBOXONE || PX_PS4) && !defined(__CUDACC__) + #if defined PX_PHYSX_COMMON_EXPORTS + #define PX_PHYSX_COMMON_API __declspec(dllexport) + #else + #define PX_PHYSX_COMMON_API __declspec(dllimport) + #endif + #elif PX_UNIX_FAMILY + #define PX_PHYSX_COMMON_API PX_UNIX_EXPORT + #else + #define PX_PHYSX_COMMON_API + #endif +#endif + +// Changing these parameters requires recompilation of the SDK + +#if !PX_DOXYGEN +namespace physx +{ +#endif + class PxCollection; + class PxBase; + + class PxHeightField; + class PxHeightFieldDesc; + + class PxTriangleMesh; + class PxConvexMesh; + + typedef PxU32 PxTriangleID; + typedef PxU16 PxMaterialTableIndex; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/common/PxPhysicsInsertionCallback.h b/sources/PhysX/PhysX/include/common/PxPhysicsInsertionCallback.h new file mode 100644 index 00000000..6b29f776 --- /dev/null +++ b/sources/PhysX/PhysX/include/common/PxPhysicsInsertionCallback.h @@ -0,0 +1,84 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_PX_PHYSICS_INSERTION_CALLBACK +#define PX_PHYSICS_PX_PHYSICS_INSERTION_CALLBACK + +#include "common/PxBase.h" + +/** \addtogroup common +@{ +*/ + +#if !PX_DOXYGEN +namespace physx +{ +#endif + + /** + + \brief Callback interface that permits PxCooking to insert a + TriangleMesh, HeightfieldMesh or ConvexMesh directly into PxPhysics without the need to store + the cooking results into a stream. + + + Using this is advised only if real-time cooking is required; using "offline" cooking and + streams is otherwise preferred. + + The default PxPhysicsInsertionCallback implementation must be used. The PxPhysics + default callback can be obtained using the PxPhysics::getPhysicsInsertionCallback(). + + @see PxCooking PxPhysics + */ + class PxPhysicsInsertionCallback + { + public: + PxPhysicsInsertionCallback() {} + + /** + \brief Builds object (TriangleMesh, HeightfieldMesh or ConvexMesh) from given data in PxPhysics. + + \param type Object type to build. + \param data Object data + \return PxBase Created object in PxPhysics. + */ + virtual PxBase* buildObjectFromData(PxConcreteType::Enum type, void* data) = 0; + + protected: + virtual ~PxPhysicsInsertionCallback() {} + }; + + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/common/PxProfileZone.h b/sources/PhysX/PhysX/include/common/PxProfileZone.h new file mode 100644 index 00000000..17f04294 --- /dev/null +++ b/sources/PhysX/PhysX/include/common/PxProfileZone.h @@ -0,0 +1,51 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. + +#ifndef PXFOUNDATION_PXPROFILEZONE_H +#define PXFOUNDATION_PXPROFILEZONE_H + +#include "foundation/PxProfiler.h" +#include "PxFoundation.h" + +#if PX_DEBUG || PX_CHECKED || PX_PROFILE + #define PX_PROFILE_ZONE(x, y) \ + physx::PxProfileScoped PX_CONCAT(_scoped, __LINE__)(PxGetProfilerCallback(), x, false, y) + #define PX_PROFILE_START_CROSSTHREAD(x, y) \ + if(PxGetProfilerCallback()) \ + PxGetProfilerCallback()->zoneStart(x, true, y) + #define PX_PROFILE_STOP_CROSSTHREAD(x, y) \ + if(PxGetProfilerCallback()) \ + PxGetProfilerCallback()->zoneEnd(NULL, x, true, y) +#else + #define PX_PROFILE_ZONE(x, y) + #define PX_PROFILE_START_CROSSTHREAD(x, y) + #define PX_PROFILE_STOP_CROSSTHREAD(x, y) +#endif + +#define PX_PROFILE_POINTER_TO_U64(pointer) static_cast(reinterpret_cast(pointer)) + +#endif // PXFOUNDATION_PXPROFILEZONE_H diff --git a/sources/PhysX/PhysX/include/common/PxRenderBuffer.h b/sources/PhysX/PhysX/include/common/PxRenderBuffer.h new file mode 100644 index 00000000..12fb6cf3 --- /dev/null +++ b/sources/PhysX/PhysX/include/common/PxRenderBuffer.h @@ -0,0 +1,157 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_FOUNDATION_PXRENDERBUFFER_H +#define PX_FOUNDATION_PXRENDERBUFFER_H + +/** \addtogroup common +@{ +*/ + +#include "common/PxPhysXCommonConfig.h" +#include "foundation/PxVec3.h" +#include "foundation/PxMat33.h" +#include "foundation/PxBounds3.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief Default color values used for debug rendering. +*/ +struct PxDebugColor +{ + enum Enum + { + eARGB_BLACK = 0xff000000, + eARGB_RED = 0xffff0000, + eARGB_GREEN = 0xff00ff00, + eARGB_BLUE = 0xff0000ff, + eARGB_YELLOW = 0xffffff00, + eARGB_MAGENTA = 0xffff00ff, + eARGB_CYAN = 0xff00ffff, + eARGB_WHITE = 0xffffffff, + eARGB_GREY = 0xff808080, + eARGB_DARKRED = 0x88880000, + eARGB_DARKGREEN = 0x88008800, + eARGB_DARKBLUE = 0x88000088 + }; +}; + +/** +\brief Used to store a single point and colour for debug rendering. +*/ +struct PxDebugPoint +{ + PxDebugPoint(const PxVec3& p, const PxU32& c) + : pos(p), color(c) {} + + PxVec3 pos; + PxU32 color; +}; + +/** +\brief Used to store a single line and colour for debug rendering. +*/ +struct PxDebugLine +{ + PxDebugLine(const PxVec3& p0, const PxVec3& p1, const PxU32& c) + : pos0(p0), color0(c), pos1(p1), color1(c) {} + + PxVec3 pos0; + PxU32 color0; + PxVec3 pos1; + PxU32 color1; +}; + +/** +\brief Used to store a single triangle and colour for debug rendering. +*/ +struct PxDebugTriangle +{ + PxDebugTriangle(const PxVec3& p0, const PxVec3& p1, const PxVec3& p2, const PxU32& c) + : pos0(p0), color0(c), pos1(p1), color1(c), pos2(p2), color2(c) {} + + PxVec3 pos0; + PxU32 color0; + PxVec3 pos1; + PxU32 color1; + PxVec3 pos2; + PxU32 color2; +}; + +/** +\brief Used to store a text for debug rendering. Doesn't own 'string' array. +*/ +struct PxDebugText +{ + PxDebugText() : string(0) {} + + PxDebugText(const PxVec3& p, const PxReal& s, const PxU32& c, const char* str) + : position(p), size(s), color(c), string(str) {} + + PxVec3 position; + PxReal size; + PxU32 color; + const char* string; +}; + +/** +\brief Interface for points, lines, triangles, and text buffer. +*/ +class PxRenderBuffer +{ +public: + virtual ~PxRenderBuffer() {} + + virtual PxU32 getNbPoints() const = 0; + virtual const PxDebugPoint* getPoints() const = 0; + + virtual PxU32 getNbLines() const = 0; + virtual const PxDebugLine* getLines() const = 0; + + virtual PxU32 getNbTriangles() const = 0; + virtual const PxDebugTriangle* getTriangles() const = 0; + + virtual PxU32 getNbTexts() const = 0; + virtual const PxDebugText* getTexts() const = 0; + + virtual void append(const PxRenderBuffer& other) = 0; + virtual void clear() = 0; +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/common/PxSerialFramework.h b/sources/PhysX/PhysX/include/common/PxSerialFramework.h new file mode 100644 index 00000000..0dfd0668 --- /dev/null +++ b/sources/PhysX/PhysX/include/common/PxSerialFramework.h @@ -0,0 +1,399 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_COMMON_NX_SERIAL_FRAMEWORK +#define PX_PHYSICS_COMMON_NX_SERIAL_FRAMEWORK + +/** \addtogroup common +@{ +*/ + +#include "common/PxPhysXCommonConfig.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +typedef PxU16 PxType; +class PxBase; +class PxSerializationContext; +class PxRepXSerializer; +class PxSerializer; +class PxPhysics; + +//! Default serialization alignment +#define PX_SERIAL_ALIGN 16 + +//! Serialized input data must be aligned to this value +#define PX_SERIAL_FILE_ALIGN 128 + +//! PxSerialObjectId value for objects that do not have an ID +#define PX_SERIAL_OBJECT_ID_INVALID 0 + +//! ID type for PxBase objects in a PxCollection +typedef PxU64 PxSerialObjectId; + +//! Bit to mark pointer type references, @see PxDeserializationContext +#define PX_SERIAL_REF_KIND_PTR_TYPE_BIT (1u<<31) + +//! Reference kind value for PxBase objects +#define PX_SERIAL_REF_KIND_PXBASE (0 | PX_SERIAL_REF_KIND_PTR_TYPE_BIT) + +//! Reference kind value for material indices +#define PX_SERIAL_REF_KIND_MATERIAL_IDX (1) + +//! Used to fix multi-byte characters warning from gcc for situations like: PxU32 foo = 'CCTS'; +#define PX_MAKE_FOURCC(a, b, c, d) ( (a) | ((b)<<8) | ((c)<<16) | ((d)<<24) ) + +/** +\brief Callback class used to process PxBase objects. + +@see PxSerializer::requires +*/ +class PxProcessPxBaseCallback +{ +public: + virtual ~PxProcessPxBaseCallback() {} + virtual void process(PxBase&) = 0; +}; + + +/** +\brief Binary serialization context class. + +This class is used to register reference values and write object +and object extra data during serialization. +It is mainly used by the serialization framework. Except for custom +serializable types, users should not have to worry about it. + +@see PxDeserializationContext +*/ +class PxSerializationContext +{ +public: + + /** + \brief Registers a reference value corresponding to a PxBase object. + + This method is assumed to be called in the implementation of PxSerializer::registerReferences for serialized + references that need to be resolved on deserialization. + + A reference needs to be associated with exactly one PxBase object in either the collection or the + external references collection. + + Different kinds of references are supported and need to be specified. In the most common case + (PX_SERIAL_REF_KIND_PXBASE) the PxBase object matches the reference value (which is the pointer + to the PxBase object). Integer references maybe registered as well (used for internal material + indices with PX_SERIAL_REF_KIND_MATERIAL_IDX). Other kinds could be added with the restriction that + for pointer types the kind value needs to be marked with the PX_SERIAL_REF_KIND_PTR_TYPE_BIT. + + \param[in] base PxBase object associated with the reference + \param[in] kind What kind of reference this is (PX_SERIAL_REF_KIND_PXBASE, PX_SERIAL_REF_KIND_MATERIAL_IDX or custom kind) + \param[in] reference Value of reference + + @see PxDeserializationContext::resolveReference, PX_SERIAL_REF_KIND_PXBASE, PX_SERIAL_REF_KIND_MATERIAL_IDX, PxSerializer::registerReferences + */ + virtual void registerReference(PxBase& base, PxU32 kind, size_t reference) = 0; + + /** + \brief Returns the collection that is being serialized. + */ + virtual const PxCollection& getCollection() const = 0; + + /** + \brief Serializes object data and object extra data. + + This function is assumed to be called within the implementation of PxSerializer::exportData and PxSerializer::exportExtraData. + + @see PxSerializer::exportData, PxSerializer::exportExtraData, PxSerializer::createObject, PxDeserializationContext::readExtraData + */ + virtual void writeData(const void* data, PxU32 size) = 0; + + /** + \brief Aligns the serialized data. + + This function is assumed to be called within the implementation of PxSerializer::exportData and PxSerializer::exportExtraData. + + @see PxSerializer::exportData, PxSerializer::exportExtraData, PxDeserializationContext::alignExtraData + */ + virtual void alignData(PxU32 alignment = PX_SERIAL_ALIGN) = 0; + + /** + \brief Helper function to write a name to the extraData if serialization is configured to save names. + + This function is assumed to be called within the implementation of PxSerializer::exportExtraData. + + @see PxSerialization::serializeCollectionToBinary, PxDeserializationContext::readName + */ + virtual void writeName(const char* name) = 0; + +protected: + + PxSerializationContext() {} + virtual ~PxSerializationContext() {} +}; + + +/** +\brief Binary deserialization context class. + +This class is used to resolve references and access extra data during deserialization. +It is mainly used by the serialization framework. Except for custom +serializable types, users should not have to worry about it. + +@see PxSerializationContext +*/ +class PxDeserializationContext +{ +public: + + /** + \brief Retrieves a pointer to a deserialized PxBase object given a corresponding deserialized reference value + + This method is assumed to be called in the implementation of PxSerializer::createObject in order + to update reference values on deserialization. + + To update a PxBase reference the corresponding deserialized pointer value needs to be provided in order to retrieve + the location of the corresponding deserialized PxBase object. (PxDeserializationContext::translatePxBase simplifies + this common case). + + For other kinds of references the reverence values need to be updated by deduction given the corresponding PxBase instance. + + \param[in] kind What kind of reference this is (PX_SERIAL_REF_KIND_PXBASE, PX_SERIAL_REF_KIND_MATERIAL_IDX or custom kind) + \param[in] reference Deserialized reference value + \return PxBase object associated with the reference value + + @see PxSerializationContext::registerReference, PX_SERIAL_REF_KIND_PXBASE, PX_SERIAL_REF_KIND_MATERIAL_IDX, translatePxBase + */ + virtual PxBase* resolveReference(PxU32 kind, size_t reference) const = 0; + + /** + \brief Helper function to update PxBase pointer on deserialization + + @see resolveReference, PX_SERIAL_REF_KIND_PXBASE + */ + template + void translatePxBase(T*& base) { if (base) { base = static_cast(resolveReference(PX_SERIAL_REF_KIND_PXBASE, size_t(base))); } } + + /** + \brief Helper function to read a name from the extra data during deserialization. + + This function is assumed to be called within the implementation of PxSerializer::createObject. + + @see PxSerializationContext::writeName + */ + PX_INLINE void readName(const char*& name) + { + PxU32 len = *reinterpret_cast(mExtraDataAddress); + mExtraDataAddress += sizeof(len); + name = len ? reinterpret_cast(mExtraDataAddress) : NULL; + mExtraDataAddress += len; + } + + /** + \brief Function to read extra data during deserialization. + + This function is assumed to be called within the implementation of PxSerializer::createObject. + + @see PxSerializationContext::writeData, PxSerializer::createObject + */ + template + PX_INLINE T* readExtraData(PxU32 count=1) + { + T* data = reinterpret_cast(mExtraDataAddress); + mExtraDataAddress += sizeof(T)*count; + return data; + } + + /** + \brief Function to read extra data during deserialization optionally aligning the extra data stream before reading. + + This function is assumed to be called within the implementation of PxSerializer::createObject. + + @see PxSerializationContext::writeData, PxDeserializationContext::alignExtraData, PxSerializer::createObject + */ + template + PX_INLINE T* readExtraData(PxU32 count=1) + { + alignExtraData(alignment); + return readExtraData(count); + } + + /** + \brief Function to align the extra data stream to a power of 2 alignment + + This function is assumed to be called within the implementation of PxSerializer::createObject. + + @see PxSerializationContext::alignData, PxSerializer::createObject + */ + PX_INLINE void alignExtraData(PxU32 alignment = PX_SERIAL_ALIGN) + { + size_t addr = reinterpret_cast(mExtraDataAddress); + addr = (addr+alignment-1)&~size_t(alignment-1); + mExtraDataAddress = reinterpret_cast(addr); + } + +protected: + + PxDeserializationContext() {} + virtual ~PxDeserializationContext() {} + + PxU8* mExtraDataAddress; +}; + +/** +\brief Callback type for exporting binary meta data for a serializable type. +@see PxSerializationRegistry::registerBinaryMetaDataCallback + +\param stream Stream to store binary meta data. +*/ +typedef void (*PxBinaryMetaDataCallback)(PxOutputStream& stream); + +/** +\brief Class serving as a registry for XML (RepX) and binary serializable types. + +In order to serialize and deserialize objects the application needs +to maintain an instance of this class. It can be created with +PxSerialization::createSerializationRegistry() and released with +PxSerializationRegistry::release(). + +@see PxSerialization::createSerializationRegistry +*/ +class PxSerializationRegistry +{ +public: + /************************************************************************************************/ + + /** @name Binary Serialization Functionality + */ + //@{ + + /** + \brief Register a serializer for a concrete type + + \param type PxConcreteType corresponding to the serializer + \param serializer The PxSerializer to be registered + + @see PxConcreteType, PxSerializer, PxSerializationRegistry::unregisterSerializer + */ + virtual void registerSerializer(PxType type, PxSerializer& serializer) = 0; + + /** + \brief Unregister a serializer for a concrete type, and retrieves the corresponding serializer object. + + \param type PxConcreteType for which the serializer should be unregistered + \return Unregistered serializer corresponding to type, NULL for types for which no serializer has been registered. + + @see PxConcreteType, PxSerializationRegistry::registerSerializer, PxSerializationRegistry::release + */ + virtual PxSerializer* unregisterSerializer(PxType type) = 0; + + /** + \brief Register binary meta data callback + + The callback is executed when calling PxSerialization::dumpBinaryMetaData. + + \param callback PxBinaryMetaDataCallback to be registered. + + @see PxBinaryMetaDataCallback, PxSerialization::dumpBinaryMetaData + */ + virtual void registerBinaryMetaDataCallback(PxBinaryMetaDataCallback callback) = 0; + + /** + \brief Returns PxSerializer corresponding to type + + \param type PxConcreteType of the serializer requested. + \return Registered PxSerializer object corresponding to type + + @see PxConcreteType + */ + virtual const PxSerializer* getSerializer(PxType type) const = 0; + + //@} + /************************************************************************************************/ + + /** @name RepX (XML) Serialization Functionality + */ + //@{ + + /** + \brief Register a RepX serializer for a concrete type + + \param type PxConcreteType corresponding to the RepX serializer + \param serializer The PxRepXSerializer to be registered + + @see PxConcreteType, PxRepXSerializer + */ + virtual void registerRepXSerializer(PxType type, PxRepXSerializer& serializer) = 0; + + /** + \brief Unregister a RepX serializer for a concrete type, and retrieves the corresponding serializer object. + + \param type PxConcreteType for which the RepX serializer should be unregistered + \return Unregistered PxRepxSerializer corresponding to type, NULL for types for which no RepX serializer has been registered. + + @see PxConcreteType, PxSerializationRegistry::registerRepXSerializer, PxSerializationRegistry::release + */ + virtual PxRepXSerializer* unregisterRepXSerializer(PxType type) = 0; + + /** + \brief Returns RepX serializer given the corresponding type name + + \param typeName Name of the type + \return Registered PxRepXSerializer object corresponding to type name + + @see PxRepXSerializer, PxTypeInfo, PX_DEFINE_TYPEINFO + */ + virtual PxRepXSerializer* getRepXSerializer(const char* typeName) const = 0; + + //@} + /************************************************************************************************/ + + /** + \brief Releases PxSerializationRegistry instance. + + This unregisters all PhysX and PhysXExtension serializers. Make sure to unregister all custom type + serializers before releasing the PxSerializationRegistry. + + @see PxSerializationRegistry::unregisterSerializer, PxSerializationRegistry::unregisterRepXSerializer + */ + virtual void release() = 0; + +protected: + virtual ~PxSerializationRegistry(){} +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/common/PxSerializer.h b/sources/PhysX/PhysX/include/common/PxSerializer.h new file mode 100644 index 00000000..b68b302c --- /dev/null +++ b/sources/PhysX/PhysX/include/common/PxSerializer.h @@ -0,0 +1,265 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_SERIALIZER_H +#define PX_SERIALIZER_H +/** \addtogroup extensions +@{ +*/ + +#include "foundation/PxAssert.h" +#include "foundation/PxAllocatorCallback.h" +#include "common/PxSerialFramework.h" +#include "common/PxCollection.h" +#include "PxFoundation.h" + + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** + \brief Serialization interface class. + + PxSerializer is used to extend serializable PxBase classes with serialization functionality. The + interface is structured such that per-class adapter instances can be used as opposed to per-object + adapter instances, avoiding per object allocations. Hence the methods take a reference to PxBase as a parameter. + + The PxSerializer interface needs to be implemented for binary or RepX serialization to work on custom + types. If only RepX serialization is needed, some methods can be left empty, as they are only needed + for binary serialization. + + A default implementation is available as a template adapter (PxSerializerDefaultAdapter). + + @see PxSerializerDefaultAdapter, PX_NEW_SERIALIZER_ADAPTER, PxSerializationRegistry::registerSerializer +*/ +class PxSerializer +{ +public: + + /**********************************************************************************************************************/ + + /** @name Basics needed for Binary- and RepX-Serialization + */ + //@{ + + /** + \brief Returns string name of dynamic type. + + \return Class name of most derived type of this object. + */ + virtual const char* getConcreteTypeName() const = 0; + + /** + \brief Adds required objects to the collection. + + This method does not add the required objects recursively, e.g. objects required by required objects. + + @see PxCollection, PxSerialization::complete + */ + virtual void requiresObjects(PxBase&, PxProcessPxBaseCallback&) const = 0; + + /** + \brief Whether the object is subordinate. + + A class is subordinate, if it can only be instantiated in the context of another class. + + \return Whether the class is subordinate + + @see PxSerialization::isSerializable + */ + virtual bool isSubordinate() const = 0; + + //@} + /**********************************************************************************************************************/ + + /**********************************************************************************************************************/ + + /** @name Functionality needed for Binary Serialization only + */ + //@{ + + /** + \brief Exports object's extra data to stream. + */ + virtual void exportExtraData(PxBase&, PxSerializationContext&) const = 0; + + /** + \brief Exports object's data to stream. + */ + virtual void exportData(PxBase&, PxSerializationContext&) const = 0; + + /** + \brief Register references that the object maintains to other objects. + */ + virtual void registerReferences(PxBase& obj, PxSerializationContext& s) const = 0; + + /** + \brief Returns size needed to create the class instance. + + \return sizeof class instance. + */ + virtual size_t getClassSize() const = 0; + + /** + \brief Create object at a given address, resolve references and import extra data. + + \param address Location at which object is created. Address is increased by the size of the created object. + \param context Context for reading external data and resolving references. + \return Created PxBase pointer (needs to be identical to address before increment). + */ + virtual PxBase* createObject(PxU8*& address, PxDeserializationContext& context) const = 0; + + //@} + /**********************************************************************************************************************/ + virtual ~PxSerializer() {} +}; + + +/** + \brief Default PxSerializer implementation. +*/ +template +class PxSerializerDefaultAdapter : public PxSerializer +{ +public: + + /************************************************************************************************/ + + /** @name Basics needed for Binary- and RepX-Serialization + */ + //@{ + + PxSerializerDefaultAdapter(const char* name) : mTypeName(name){} + + virtual const char* getConcreteTypeName() const + { + return mTypeName; + } + + virtual void requiresObjects(PxBase& obj, PxProcessPxBaseCallback& c) const + { + T& t = static_cast(obj); + t.requiresObjects(c); + } + + virtual bool isSubordinate() const + { + return false; + } + + //@} + /************************************************************************************************/ + + /** @name Functionality needed for Binary Serialization only + */ + //@{ + + // object methods + + virtual void exportExtraData(PxBase& obj, PxSerializationContext& s) const + { + T& t = static_cast(obj); + t.exportExtraData(s); + } + + virtual void exportData(PxBase& obj, PxSerializationContext& s) const + { + PxAllocatorCallback& allocator = PxGetFoundation().getAllocatorCallback(); + T* copy = reinterpret_cast(allocator.allocate(sizeof(T), "TmpAllocExportData", __FILE__, __LINE__)); + PxMemCopy(copy, &obj, sizeof(T)); + copy->preExportDataReset(); + s.writeData(copy, sizeof(T)); + allocator.deallocate(copy); + } + + virtual void registerReferences(PxBase& obj, PxSerializationContext& s) const + { + T& t = static_cast(obj); + + s.registerReference(obj, PX_SERIAL_REF_KIND_PXBASE, size_t(&obj)); + + struct RequiresCallback : public PxProcessPxBaseCallback + { + RequiresCallback(PxSerializationContext& c) : context(c) {} + RequiresCallback& operator=(RequiresCallback&) { PX_ASSERT(0); return *this; } + void process(physx::PxBase& base) + { + context.registerReference(base, PX_SERIAL_REF_KIND_PXBASE, size_t(&base)); + } + PxSerializationContext& context; + }; + + RequiresCallback callback(s); + t.requiresObjects(callback); + } + + // class methods + + virtual size_t getClassSize() const + { + return sizeof(T); + } + + virtual PxBase* createObject(PxU8*& address, PxDeserializationContext& context) const + { + return T::createObject(address, context); + } + + + //@} + /************************************************************************************************/ + +private: + const char* mTypeName; +}; + +/** + \brief Preprocessor Macro to simplify adapter creation. + + Note: that the allocator used for creation needs to match with the one used in PX_DELETE_SERIALIZER_ADAPTER. +*/ +#define PX_NEW_SERIALIZER_ADAPTER(x) \ + *new( PxGetFoundation().getAllocatorCallback().allocate(sizeof(PxSerializerDefaultAdapter), \ + "PxSerializerDefaultAdapter", __FILE__, __LINE__ )) PxSerializerDefaultAdapter(#x) + +/** + \brief Preprocessor Macro to simplify adapter deletion. +*/ +#define PX_DELETE_SERIALIZER_ADAPTER(x) \ + { PxSerializer* s = x; if (s) { s->~PxSerializer(); PxGetFoundation().getAllocatorCallback().deallocate(s); } } + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/common/PxStringTable.h b/sources/PhysX/PhysX/include/common/PxStringTable.h new file mode 100644 index 00000000..2af44004 --- /dev/null +++ b/sources/PhysX/PhysX/include/common/PxStringTable.h @@ -0,0 +1,73 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_STRING_TABLE_H +#define PX_STRING_TABLE_H + +#include "foundation/PxPreprocessor.h" + +/** \addtogroup physics +@{ +*/ + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** + * \brief a table to manage strings. Strings allocated through this object are expected to be owned by this object. + */ +class PxStringTable +{ +protected: + virtual ~PxStringTable(){} +public: + /** + * \brief Allocate a new string. + * + * \param[in] inSrc Source string, null terminated or null. + * + * \return *Always* a valid null terminated string. "" is returned if "" or null is passed in. + */ + virtual const char* allocateStr( const char* inSrc ) = 0; + + /** + * Release the string table and all the strings associated with it. + */ + virtual void release() = 0; +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/common/PxTolerancesScale.h b/sources/PhysX/PhysX/include/common/PxTolerancesScale.h new file mode 100644 index 00000000..c34f5322 --- /dev/null +++ b/sources/PhysX/PhysX/include/common/PxTolerancesScale.h @@ -0,0 +1,108 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_SCALE_H +#define PX_SCALE_H + +/** \addtogroup common + @{ +*/ + +#include "common/PxPhysXCommonConfig.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxPhysics; + +/** +\brief Class to define the scale at which simulation runs. Most simulation tolerances are +calculated in terms of the values here. + +\note if you change the simulation scale, you will probablly also wish to change the scene's +default value of gravity, and stable simulation will probably require changes to the scene's +bounceThreshold also. +*/ + +class PxTolerancesScale +{ +public: + + /** brief + The approximate size of objects in the simulation. + + For simulating roughly human-sized in metric units, 1 is a good choice. + If simulation is done in centimetres, use 100 instead. This is used to + estimate certain length-related tolerances. + */ + PxReal length; + + /** brief + The typical magnitude of velocities of objects in simulation. This is used to estimate + whether a contact should be treated as bouncing or resting based on its impact velocity, + and a kinetic energy threshold below which the simulation may put objects to sleep. + + For normal physical environments, a good choice is the approximate speed of an object falling + under gravity for one second. + */ + PxReal speed; + + /** + \brief constructor sets to default + */ + PX_INLINE PxTolerancesScale(); + + /** + \brief Returns true if the descriptor is valid. + \return true if the current settings are valid (returns always true). + */ + PX_INLINE bool isValid() const; + +}; + +PX_INLINE PxTolerancesScale::PxTolerancesScale(): + length(1.0f), + speed(10.0f) + { + } + +PX_INLINE bool PxTolerancesScale::isValid() const +{ + return length>0.0f; +} + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/common/PxTypeInfo.h b/sources/PhysX/PhysX/include/common/PxTypeInfo.h new file mode 100644 index 00000000..72b3c2dd --- /dev/null +++ b/sources/PhysX/PhysX/include/common/PxTypeInfo.h @@ -0,0 +1,128 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_PHYSICS_COMMON_PX_TYPEINFO +#define PX_PHYSICS_COMMON_PX_TYPEINFO + +/** \addtogroup common +@{ +*/ + +#include "common/PxPhysXCommonConfig.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief an enumeration of concrete classes inheriting from PxBase + +Enumeration space is reserved for future PhysX core types, PhysXExtensions, +PhysXVehicle and Custom application types. + +@see PxBase, PxTypeInfo +*/ + +struct PxConcreteType +{ + enum Enum + { + eUNDEFINED, + + eHEIGHTFIELD, + eCONVEX_MESH, + eTRIANGLE_MESH_BVH33, + eTRIANGLE_MESH_BVH34, + + eRIGID_DYNAMIC, + eRIGID_STATIC, + eSHAPE, + eMATERIAL, + eCONSTRAINT, + eAGGREGATE, + eARTICULATION, + eARTICULATION_REDUCED_COORDINATE, + eARTICULATION_LINK, + eARTICULATION_JOINT, + eARTICULATION_JOINT_REDUCED_COORDINATE, + ePRUNING_STRUCTURE, + eBVH_STRUCTURE, + + ePHYSX_CORE_COUNT, + eFIRST_PHYSX_EXTENSION = 256, + eFIRST_VEHICLE_EXTENSION = 512, + eFIRST_USER_EXTENSION = 1024 + }; +}; + +/** +\brief a structure containing per-type information for types inheriting from PxBase + +@see PxBase, PxConcreteType +*/ + +template struct PxTypeInfo {}; + +#define PX_DEFINE_TYPEINFO(_name, _fastType) \ + class _name; \ + template <> struct PxTypeInfo<_name> { static const char* name() { return #_name; } enum { eFastTypeId = _fastType }; }; + +/* the semantics of the fastType are as follows: an object A can be cast to a type B if B's fastType is defined, and A has the same fastType. + * This implies that B has no concrete subclasses or superclasses. + */ + +PX_DEFINE_TYPEINFO(PxBase, PxConcreteType::eUNDEFINED) +PX_DEFINE_TYPEINFO(PxMaterial, PxConcreteType::eMATERIAL) +PX_DEFINE_TYPEINFO(PxConvexMesh, PxConcreteType::eCONVEX_MESH) +PX_DEFINE_TYPEINFO(PxTriangleMesh, PxConcreteType::eUNDEFINED) +PX_DEFINE_TYPEINFO(PxBVH33TriangleMesh, PxConcreteType::eTRIANGLE_MESH_BVH33) +PX_DEFINE_TYPEINFO(PxBVH34TriangleMesh, PxConcreteType::eTRIANGLE_MESH_BVH34) +PX_DEFINE_TYPEINFO(PxHeightField, PxConcreteType::eHEIGHTFIELD) +PX_DEFINE_TYPEINFO(PxActor, PxConcreteType::eUNDEFINED) +PX_DEFINE_TYPEINFO(PxRigidActor, PxConcreteType::eUNDEFINED) +PX_DEFINE_TYPEINFO(PxRigidBody, PxConcreteType::eUNDEFINED) +PX_DEFINE_TYPEINFO(PxRigidDynamic, PxConcreteType::eRIGID_DYNAMIC) +PX_DEFINE_TYPEINFO(PxRigidStatic, PxConcreteType::eRIGID_STATIC) +PX_DEFINE_TYPEINFO(PxArticulationLink, PxConcreteType::eARTICULATION_LINK) +PX_DEFINE_TYPEINFO(PxArticulationJoint, PxConcreteType::eARTICULATION_JOINT) +PX_DEFINE_TYPEINFO(PxArticulationJointReducedCoordinate, PxConcreteType::eARTICULATION_JOINT_REDUCED_COORDINATE) +PX_DEFINE_TYPEINFO(PxArticulation, PxConcreteType::eARTICULATION) +PX_DEFINE_TYPEINFO(PxArticulationReducedCoordinate, PxConcreteType::eARTICULATION_REDUCED_COORDINATE) +PX_DEFINE_TYPEINFO(PxAggregate, PxConcreteType::eAGGREGATE) +PX_DEFINE_TYPEINFO(PxConstraint, PxConcreteType::eCONSTRAINT) +PX_DEFINE_TYPEINFO(PxShape, PxConcreteType::eSHAPE) +PX_DEFINE_TYPEINFO(PxPruningStructure, PxConcreteType::ePRUNING_STRUCTURE) + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/common/windows/PxWindowsDelayLoadHook.h b/sources/PhysX/PhysX/include/common/windows/PxWindowsDelayLoadHook.h new file mode 100644 index 00000000..5a7b178d --- /dev/null +++ b/sources/PhysX/PhysX/include/common/windows/PxWindowsDelayLoadHook.h @@ -0,0 +1,102 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_DELAY_LOAD_HOOK +#define PX_PHYSICS_DELAY_LOAD_HOOK + +#include "foundation/PxPreprocessor.h" +#include "common/PxPhysXCommonConfig.h" + +/** \addtogroup foundation +@{ +*/ + +#if !PX_DOXYGEN +namespace physx +{ +#endif + /** + \brief PxDelayLoadHook + + This is a helper class for delay loading the PhysXCommon dll and PhysXFoundation dll. + If a PhysXCommon dll or PhysXFoundation dll with a non-default file name needs to be loaded, + PxDelayLoadHook can be sub-classed to provide the custom filenames. + + Once the names are set, the instance must be set for use by PhysX.dll using PxSetPhysXDelayLoadHook(), + PhysXCooking.dll using PxSetPhysXCookingDelayLoadHook() or by PhysXCommon.dll using PxSetPhysXCommonDelayLoadHook(). + + @see PxSetPhysXDelayLoadHook(), PxSetPhysXCookingDelayLoadHook(), PxSetPhysXCommonDelayLoadHook() + */ + class PxDelayLoadHook + { + public: + PxDelayLoadHook() {} + virtual ~PxDelayLoadHook() {} + + virtual const char* getPhysXFoundationDllName() const = 0; + + virtual const char* getPhysXCommonDllName() const = 0; + + protected: + private: + }; + + /** + \brief Sets delay load hook instance for PhysX dll. + + \param[in] hook Delay load hook. + + @see PxDelayLoadHook + */ + PX_C_EXPORT PX_PHYSX_CORE_API void PX_CALL_CONV PxSetPhysXDelayLoadHook(const physx::PxDelayLoadHook* hook); + + /** + \brief Sets delay load hook instance for PhysXCooking dll. + + \param[in] hook Delay load hook. + + @see PxDelayLoadHook + */ + PX_C_EXPORT PX_PHYSX_CORE_API void PX_CALL_CONV PxSetPhysXCookingDelayLoadHook(const physx::PxDelayLoadHook* hook); + + /** + \brief Sets delay load hook instance for PhysXCommon dll. + + \param[in] hook Delay load hook. + + @see PxDelayLoadHook + */ + PX_C_EXPORT PX_PHYSX_COMMON_API void PX_CALL_CONV PxSetPhysXCommonDelayLoadHook(const physx::PxDelayLoadHook* hook); + +#if !PX_DOXYGEN +} // namespace physx +#endif +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/cooking/PxBVH33MidphaseDesc.h b/sources/PhysX/PhysX/include/cooking/PxBVH33MidphaseDesc.h new file mode 100644 index 00000000..25e3e137 --- /dev/null +++ b/sources/PhysX/PhysX/include/cooking/PxBVH33MidphaseDesc.h @@ -0,0 +1,110 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_BVH_33_MIDPHASE_DESC_H +#define PX_BVH_33_MIDPHASE_DESC_H +/** \addtogroup cooking +@{ +*/ + +#include "foundation/PxPreprocessor.h" +#include "foundation/PxSimpleTypes.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** \brief Enumeration for mesh cooking hints. */ +struct PxMeshCookingHint +{ + enum Enum + { + eSIM_PERFORMANCE = 0, //!< Default value. Favors higher quality hierarchy with higher runtime performance over cooking speed. + eCOOKING_PERFORMANCE = 1 //!< Enables fast cooking path at the expense of somewhat lower quality hierarchy construction. + }; +}; + +/** + +\brief Structure describing parameters affecting BVH33 midphase mesh structure. + +@see PxCookingParams, PxMidphaseDesc +*/ +struct PxBVH33MidphaseDesc +{ + /** + \brief Controls the trade-off between mesh size and runtime performance. + + Using a value of 1.0 will produce a larger cooked mesh with generally higher runtime performance, + using 0.0 will produce a smaller cooked mesh, with generally lower runtime performance. + + Values outside of [0,1] range will be clamped and cause a warning when any mesh gets cooked. + + Default value: 0.55 + Range: [0.0f, 1.0f] + */ + PxF32 meshSizePerformanceTradeOff; + + /** + \brief Mesh cooking hint. Used to specify mesh hierarchy construction preference. + + Default value: PxMeshCookingHint::eSIM_PERFORMANCE + */ + PxMeshCookingHint::Enum meshCookingHint; + + /** + \brief Desc initialization to default value. + */ + void setToDefault() + { + meshSizePerformanceTradeOff = 0.55f; + meshCookingHint = PxMeshCookingHint::eSIM_PERFORMANCE; + } + + /** + \brief Returns true if the descriptor is valid. + \return true if the current settings are valid. + */ + bool isValid() const + { + if(meshSizePerformanceTradeOff < 0.0f || meshSizePerformanceTradeOff > 1.0f) + return false; + return true; + } +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + + + /** @} */ +#endif // PX_BVH_33_MIDPHASE_DESC_H diff --git a/sources/PhysX/PhysX/include/cooking/PxBVH34MidphaseDesc.h b/sources/PhysX/PhysX/include/cooking/PxBVH34MidphaseDesc.h new file mode 100644 index 00000000..2c9933c4 --- /dev/null +++ b/sources/PhysX/PhysX/include/cooking/PxBVH34MidphaseDesc.h @@ -0,0 +1,90 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_BVH_34_MIDPHASE_DESC_H +#define PX_BVH_34_MIDPHASE_DESC_H +/** \addtogroup cooking +@{ +*/ + +#include "foundation/PxPreprocessor.h" +#include "foundation/PxSimpleTypes.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** + +\brief Structure describing parameters affecting BVH34 midphase mesh structure. + +@see PxCookingParams, PxMidphaseDesc +*/ +struct PxBVH34MidphaseDesc +{ + /** + \brief Mesh cooking hint for max primitives per leaf limit. + Less primitives per leaf produces larger meshes with better runtime performance + and worse cooking performance. More triangles per leaf results in faster cooking speed and + smaller mesh sizes, but with worse runtime performance. + + Default value: 4 + Range: <4, 15> + */ + PxU32 numPrimsPerLeaf; + + /** + \brief Desc initialization to default value. + */ + void setToDefault() + { + numPrimsPerLeaf = 4; + } + + /** + \brief Returns true if the descriptor is valid. + \return true if the current settings are valid. + */ + bool isValid() const + { + if(numPrimsPerLeaf < 4 || numPrimsPerLeaf > 15) + return false; + return true; + } +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + + + /** @} */ +#endif // PX_BVH_34_MIDPHASE_DESC_H diff --git a/sources/PhysX/PhysX/include/cooking/PxBVHStructureDesc.h b/sources/PhysX/PhysX/include/cooking/PxBVHStructureDesc.h new file mode 100644 index 00000000..62ff9de1 --- /dev/null +++ b/sources/PhysX/PhysX/include/cooking/PxBVHStructureDesc.h @@ -0,0 +1,109 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_BVH_STRUCTURE_DESC_H +#define PX_BVH_STRUCTURE_DESC_H +/** \addtogroup cooking +@{ +*/ + +#include "common/PxCoreUtilityTypes.h" +#include "common/PxPhysXCommonConfig.h" +#include "foundation/PxTransform.h" +#include "foundation/PxBounds3.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** + +\brief Descriptor class for #PxBVHStructure. + +@see PxBVHStructure +*/ +class PxBVHStructureDesc +{ +public: + PX_INLINE PxBVHStructureDesc(); + + /** + \brief Pointer to first bounding box. + */ + PxBoundedData bounds; + + /** + \brief Initialize the BVH structure descriptor + */ + PX_INLINE void setToDefault(); + + /** + \brief Returns true if the descriptor is valid. + \return true if the current settings are valid. + */ + PX_INLINE bool isValid() const; + + +protected: +}; + + + +PX_INLINE PxBVHStructureDesc::PxBVHStructureDesc() +{ +} + +PX_INLINE void PxBVHStructureDesc::setToDefault() +{ + *this = PxBVHStructureDesc(); +} + +PX_INLINE bool PxBVHStructureDesc::isValid() const +{ + // Check BVH desc data + if(!bounds.data) + return false; + if(bounds.stride < sizeof(PxBounds3)) //should be at least one point's worth of data + return false; + + if(bounds.count == 0) + return false; + + return true; +} + +#if !PX_DOXYGEN +} // namespace physx +#endif + + + /** @} */ +#endif // PX_BVH_STRUCTURE_DESC_H diff --git a/sources/PhysX/PhysX/include/cooking/PxConvexMeshDesc.h b/sources/PhysX/PhysX/include/cooking/PxConvexMeshDesc.h new file mode 100644 index 00000000..8aa939f7 --- /dev/null +++ b/sources/PhysX/PhysX/include/cooking/PxConvexMeshDesc.h @@ -0,0 +1,307 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_COLLISION_NXCONVEXMESHDESC +#define PX_COLLISION_NXCONVEXMESHDESC +/** \addtogroup cooking +@{ +*/ + +#include "foundation/PxVec3.h" +#include "foundation/PxFlags.h" +#include "common/PxCoreUtilityTypes.h" +#include "geometry/PxConvexMesh.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief Flags which describe the format and behavior of a convex mesh. +*/ +struct PxConvexFlag +{ + enum Enum + { + /** + Denotes the use of 16-bit vertex indices in PxConvexMeshDesc::triangles or PxConvexMeshDesc::polygons. + (otherwise, 32-bit indices are assumed) + @see #PxConvexMeshDesc.indices + */ + e16_BIT_INDICES = (1<<0), + + /** + Automatically recomputes the hull from the vertices. If this flag is not set, you must provide the entire geometry manually. + + \note There are two different algorithms for hull computation, please see PxConvexMeshCookingType. + + @see PxConvexMeshCookingType + */ + eCOMPUTE_CONVEX = (1<<1), + + /** + \brief Checks and removes almost zero-area triangles during convex hull computation. + The rejected area size is specified in PxCookingParams::areaTestEpsilon + + \note This flag is only used in combination with eCOMPUTE_CONVEX. + + @see PxCookingParams PxCookingParams::areaTestEpsilon + */ + eCHECK_ZERO_AREA_TRIANGLES = (1<<2), + + /** + \brief Quantizes the input vertices using the k-means clustering + + \note The input vertices are quantized to PxConvexMeshDesc::quantizedCount + see http://en.wikipedia.org/wiki/K-means_clustering + + */ + eQUANTIZE_INPUT = (1 << 3), + + /** + \brief Disables the convex mesh validation to speed-up hull creation. Please use separate validation + function in checked/debug builds. Creating a convex mesh with invalid input data without prior validation + may result in undefined behavior. + + @see PxCooking::validateConvexMesh + */ + eDISABLE_MESH_VALIDATION = (1 << 4), + + /** + \brief Enables plane shifting vertex limit algorithm. + + Plane shifting is an alternative algorithm for the case when the computed hull has more vertices + than the specified vertex limit. + + The default algorithm computes the full hull, and an OBB around the input vertices. This OBB is then sliced + with the hull planes until the vertex limit is reached.The default algorithm requires the vertex limit + to be set to at least 8, and typically produces results that are much better quality than are produced + by plane shifting. + + When plane shifting is enabled, the hull computation stops when vertex limit is reached. The hull planes + are then shifted to contain all input vertices, and the new plane intersection points are then used to + generate the final hull with the given vertex limit.Plane shifting may produce sharp edges to vertices + very far away from the input cloud, and does not guarantee that all input vertices are inside the resulting + hull.However, it can be used with a vertex limit as low as 4. + */ + ePLANE_SHIFTING = (1 << 5), + + /** + \brief Inertia tensor computation is faster using SIMD code, but the precision is lower, which may result + in incorrect inertia for very thin hulls. + */ + eFAST_INERTIA_COMPUTATION = (1 << 6), + + /** + \brief Convex hulls are created with respect to GPU simulation limitations. Vertex limit is set to 64 and + vertex limit per face is internally set to 32. + \note Can be used only with eCOMPUTE_CONVEX flag. + */ + eGPU_COMPATIBLE = (1 << 7), + + /** + \brief Convex hull input vertices are shifted to be around origin to provide better computation stability. + It is recommended to provide input vertices around the origin, otherwise use this flag to improve + numerical stability. + \note Is used only with eCOMPUTE_CONVEX flag. + */ + eSHIFT_VERTICES = (1 << 8) + }; +}; + +/** +\brief collection of set bits defined in PxConvexFlag. + +@see PxConvexFlag +*/ +typedef PxFlags PxConvexFlags; +PX_FLAGS_OPERATORS(PxConvexFlag::Enum,PxU16) + +/** +\brief Descriptor class for #PxConvexMesh. +\note The number of vertices and the number of convex polygons in a cooked convex mesh is limited to 256. + +@see PxConvexMesh PxConvexMeshGeometry PxShape PxPhysics.createConvexMesh() + +*/ +class PxConvexMeshDesc +{ +public: + + /** + \brief Vertex positions data in PxBoundedData format. + + Default: NULL + */ + PxBoundedData points; + + /** + \brief Polygons data in PxBoundedData format. +

Pointer to first polygon.

+ + Default: NULL + + @see PxHullPolygon + */ + PxBoundedData polygons; + + /** + \brief Polygon indices data in PxBoundedData format. +

Pointer to first index.

+ + Default: NULL + +

This is declared as a void pointer because it is actually either an PxU16 or a PxU32 pointer.

+ + @see PxHullPolygon PxConvexFlag::e16_BIT_INDICES + */ + PxBoundedData indices; + + /** + \brief Flags bits, combined from values of the enum ::PxConvexFlag + + Default: 0 + */ + PxConvexFlags flags; + + /** + \brief Limits the number of vertices of the result convex mesh. Hard maximum limit is 256 + and minimum limit is 4 if PxConvexFlag::ePLANE_SHIFTING is used, otherwise the minimum + limit is 8. + + \note Vertex limit is only used when PxConvexFlag::eCOMPUTE_CONVEX is specified. + \note The please see PxConvexFlag::ePLANE_SHIFTING for algorithm explanation + + @see PxConvexFlag::ePLANE_SHIFTING + + Range: [4, 255]
+ Default: 255 + */ + PxU16 vertexLimit; + + /** + \brief Maximum number of vertices after quantization. The quantization is done during the vertex cleaning phase. + The quantization is applied when PxConvexFlag::eQUANTIZE_INPUT is specified. + + @see PxConvexFlag::eQUANTIZE_INPUT + + Range: [4, 65535]
+ Default: 255 + */ + PxU16 quantizedCount; + + /** + \brief constructor sets to default. + */ + PX_INLINE PxConvexMeshDesc(); + /** + \brief (re)sets the structure to the default. + */ + PX_INLINE void setToDefault(); + /** + \brief Returns true if the descriptor is valid. + + \return True if the current settings are valid + */ + PX_INLINE bool isValid() const; +}; + +PX_INLINE PxConvexMeshDesc::PxConvexMeshDesc() //constructor sets to default +: vertexLimit(255), quantizedCount(255) +{ +} + +PX_INLINE void PxConvexMeshDesc::setToDefault() +{ + *this = PxConvexMeshDesc(); +} + +PX_INLINE bool PxConvexMeshDesc::isValid() const +{ + // Check geometry + if(points.count < 3 || //at least 1 trig's worth of points + (points.count > 0xffff && flags & PxConvexFlag::e16_BIT_INDICES)) + return false; + if(!points.data) + return false; + if(points.stride < sizeof(PxVec3)) //should be at least one point's worth of data + return false; + if (quantizedCount < 4) + return false; + + // Check topology + if(polygons.data) + { + if(polygons.count < 4) // we require 2 neighbors for each vertex - 4 polygons at least + return false; + + if(!indices.data) // indices must be provided together with polygons + return false; + + PxU32 limit = (flags & PxConvexFlag::e16_BIT_INDICES) ? sizeof(PxU16) : sizeof(PxU32); + if(indices.stride < limit) + return false; + + limit = sizeof(PxHullPolygon); + if(polygons.stride < limit) + return false; + } + else + { + // We can compute the hull from the vertices + if(!(flags & PxConvexFlag::eCOMPUTE_CONVEX)) + return false; // If the mesh is convex and we're not allowed to compute the hull, + // you have to provide it completely (geometry & topology). + } + + if((flags & PxConvexFlag::ePLANE_SHIFTING) && vertexLimit < 4) + { + return false; + } + + if (!(flags & PxConvexFlag::ePLANE_SHIFTING) && vertexLimit < 8) + { + return false; + } + + if(vertexLimit > 256) + { + return false; + } + return true; +} + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/cooking/PxCooking.h b/sources/PhysX/PhysX/include/cooking/PxCooking.h new file mode 100644 index 00000000..94b49277 --- /dev/null +++ b/sources/PhysX/PhysX/include/cooking/PxCooking.h @@ -0,0 +1,563 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_COOKING_H +#define PX_COOKING_H +/** \addtogroup cooking +@{ +*/ +#include "common/PxPhysXCommonConfig.h" +#include "common/PxTolerancesScale.h" +#include "cooking/Pxc.h" + +#include "cooking/PxConvexMeshDesc.h" +#include "cooking/PxTriangleMeshDesc.h" +#include "cooking/PxMidphaseDesc.h" +#include "cooking/PxBVHStructureDesc.h" +#include "geometry/PxTriangleMesh.h" +#include "geometry/PxBVHStructure.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxPhysicsInsertionCallback; +class PxFoundation; + +/** +\brief Result from convex cooking. +*/ +struct PxConvexMeshCookingResult +{ + enum Enum + { + /** + \brief Convex mesh cooking succeeded. + */ + eSUCCESS, + + /** + \brief Convex mesh cooking failed, algorithm couldn't find 4 initial vertices without a small triangle. + + @see PxCookingParams::areaTestEpsilon PxConvexFlag::eCHECK_ZERO_AREA_TRIANGLES + */ + eZERO_AREA_TEST_FAILED, + + /** + \brief Convex mesh cooking succeeded, but the algorithm has reached the 255 polygons limit. + The produced hull does not contain all input vertices. Try to simplify the input vertices + or try to use the eINFLATE_CONVEX or the eQUANTIZE_INPUT flags. + + @see PxConvexFlag::eINFLATE_CONVEX PxConvexFlag::eQUANTIZE_INPUT + */ + ePOLYGONS_LIMIT_REACHED, + + /** + \brief Something unrecoverable happened. Check the error stream to find out what. + */ + eFAILURE + }; +}; + +/** \brief Enumeration for convex mesh cooking algorithms. */ +struct PxConvexMeshCookingType +{ + enum Enum + { + /** + \brief The Quickhull algorithm constructs the hull from the given input points. The resulting hull + will only contain a subset of the input points. + + */ + eQUICKHULL + }; +}; + +/** +\brief Result from triangle mesh cooking +*/ +struct PxTriangleMeshCookingResult +{ + enum Enum + { + /** + \brief Everything is A-OK. + */ + eSUCCESS = 0, + + /** + \brief a triangle is too large for well-conditioned results. Tessellate the mesh for better behavior, see the user guide section on cooking for more details. + */ + eLARGE_TRIANGLE, + + /** + \brief Something unrecoverable happened. Check the error stream to find out what. + */ + eFAILURE + }; +}; + +/** + +\brief Enum for the set of mesh pre-processing parameters. + +*/ + +struct PxMeshPreprocessingFlag +{ + enum Enum + { + /** + \brief When set, mesh welding is performed. See PxCookingParams::meshWeldTolerance. Clean mesh must be enabled. + */ + eWELD_VERTICES = 1 << 0, + + /** + \brief When set, mesh cleaning is disabled. This makes cooking faster. + + When clean mesh is not performed, mesh welding is also not performed. + + It is recommended to use only meshes that passed during validateTriangleMesh. + + */ + eDISABLE_CLEAN_MESH = 1 << 1, + + /** + \brief When set, active edges are set for each triangle edge. This makes cooking faster but slow up contact generation. + */ + eDISABLE_ACTIVE_EDGES_PRECOMPUTE = 1 << 2, + + /** + \brief When set, 32-bit indices will always be created regardless of triangle count. + + \note By default mesh will be created with 16-bit indices for triangle count <= 0xFFFF and 32-bit otherwise. + */ + eFORCE_32BIT_INDICES = 1 << 3 + }; +}; + +typedef PxFlags PxMeshPreprocessingFlags; + +/** + +\brief Structure describing parameters affecting mesh cooking. + +@see PxSetCookingParams() PxGetCookingParams() +*/ +struct PxCookingParams +{ + /** + \brief Zero-size area epsilon used in convex hull computation. + + If the area of a triangle of the hull is below this value, the triangle will be rejected. This test + is done only if PxConvexFlag::eCHECK_ZERO_AREA_TRIANGLES is used. + + @see PxConvexFlag::eCHECK_ZERO_AREA_TRIANGLES + + Default value: 0.06f*PxTolerancesScale.length*PxTolerancesScale.length + + Range: (0.0f, PX_MAX_F32) + */ + float areaTestEpsilon; + + /** + \brief Plane tolerance used in convex hull computation. + + The value is used during hull construction. When a new point is about to be added to the hull it + gets dropped when the point is closer to the hull than the planeTolerance. The planeTolerance + is increased according to the hull size. + + If 0.0f is set all points are accepted when the convex hull is created. This may lead to edge cases + where the new points may be merged into an existing polygon and the polygons plane equation might + slightly change therefore. This might lead to failures during polygon merging phase in the hull computation. + + It is recommended to use the default value, however if it is required that all points needs to be + accepted or huge thin convexes are created, it might be required to lower the default value. + + \note The plane tolerance is used only within PxConvexMeshCookingType::eQUICKHULL algorithm. + + Default value: 0.0007f + + Range: <0.0f, PX_MAX_F32) + */ + float planeTolerance; + + /** + \brief Convex hull creation algorithm. + + Default value: PxConvexMeshCookingType::eQUICKHULL + + @see PxConvexMeshCookingType + */ + PxConvexMeshCookingType::Enum convexMeshCookingType; + + /** + \brief When true, the face remap table is not created. This saves a significant amount of memory, but the SDK will + not be able to provide the remap information for internal mesh triangles returned by collisions, + sweeps or raycasts hits. + + Default value: false + */ + bool suppressTriangleMeshRemapTable; + + /** + \brief When true, the triangle adjacency information is created. You can get the adjacency triangles + for a given triangle from getTriangle. + + Default value: false + */ + bool buildTriangleAdjacencies; + + /** + \brief When true, addigional information required for GPU-accelerated rigid body simulation is created. This can increase memory usage and cooking times for convex meshes and triangle meshes. + + Default value: false + */ + bool buildGPUData; + + /** + \brief Tolerance scale is used to check if cooked triangles are not too huge. This check will help with simulation stability. + + \note The PxTolerancesScale values have to match the values used when creating a PxPhysics or PxScene instance. + + @see PxTolerancesScale + */ + PxTolerancesScale scale; + + /** + \brief Mesh pre-processing parameters. Used to control options like whether the mesh cooking performs vertex welding before cooking. + + Default value: 0 + */ + PxMeshPreprocessingFlags meshPreprocessParams; + + /** + \brief Mesh weld tolerance. If mesh welding is enabled, this controls the distance at which vertices are welded. + If mesh welding is not enabled, this value defines the acceptance distance for mesh validation. Provided no two vertices are within this distance, the mesh is considered to be + clean. If not, a warning will be emitted. Having a clean, welded mesh is required to achieve the best possible performance. + + The default vertex welding uses a snap-to-grid approach. This approach effectively truncates each vertex to integer values using meshWeldTolerance. + Once these snapped vertices are produced, all vertices that snap to a given vertex on the grid are remapped to reference a single vertex. Following this, + all triangles' indices are remapped to reference this subset of clean vertices. It should be noted that the vertices that we do not alter the + position of the vertices; the snap-to-grid is only performed to identify nearby vertices. + + The mesh validation approach also uses the same snap-to-grid approach to identify nearby vertices. If more than one vertex snaps to a given grid coordinate, + we ensure that the distance between the vertices is at least meshWeldTolerance. If this is not the case, a warning is emitted. + + Default value: 0.0 + */ + PxReal meshWeldTolerance; + + /** + \brief Controls the desired midphase desc structure for triangle meshes. + + @see PxBVH33MidphaseDesc, PxBVH34MidphaseDesc, PxMidphaseDesc + + Default value: PxMeshMidPhase::eBVH33 + */ + PxMidphaseDesc midphaseDesc; + + /** + \brief Vertex limit beyond which additional acceleration structures are computed for each convex mesh. Increase that limit to reduce memory usage. + Computing the extra structures all the time does not guarantee optimal performance. There is a per-platform break-even point below which the + extra structures actually hurt performance. + + Default value: 32 + */ + PxU32 gaussMapLimit; + + PxCookingParams(const PxTolerancesScale& sc): + areaTestEpsilon (0.06f*sc.length*sc.length), + planeTolerance (0.0007f), + convexMeshCookingType (PxConvexMeshCookingType::eQUICKHULL), + suppressTriangleMeshRemapTable (false), + buildTriangleAdjacencies (false), + buildGPUData (false), + scale (sc), + meshPreprocessParams (0), + meshWeldTolerance (0.f), + gaussMapLimit (32) + { + } +}; + +class PxCooking +{ +public: + /** + \brief Closes this instance of the interface. + + This function should be called to cleanly shut down the Cooking library before application exit. + + \note This function is required to be called to release foundation usage. + + */ + virtual void release() = 0; + + /** + \brief Sets cooking parameters + + \param[in] params Cooking parameters + + @see getParams() + */ + virtual void setParams(const PxCookingParams& params) = 0; + + /** + \brief Gets cooking parameters + + \return Current cooking parameters. + + @see PxCookingParams setParams() + */ + virtual const PxCookingParams& getParams() const = 0; + + /** + \brief Checks endianness is the same between cooking & target platforms + + \return True if there is and endian mismatch. + */ + virtual bool platformMismatch() const = 0; + + /** + \brief Cooks a triangle mesh. The results are written to the stream. + + To create a triangle mesh object it is necessary to first 'cook' the mesh data into + a form which allows the SDK to perform efficient collision detection. + + cookTriangleMesh() allows a mesh description to be cooked into a binary stream + suitable for loading and performing collision detection at runtime. + + \param[in] desc The triangle mesh descriptor to read the mesh from. + \param[in] stream User stream to output the cooked data. + \param[out] condition Result from triangle mesh cooking. + \return true on success + + @see cookConvexMesh() setParams() PxPhysics.createTriangleMesh() PxTriangleMeshCookingResult::Enum + */ + virtual bool cookTriangleMesh(const PxTriangleMeshDesc& desc, PxOutputStream& stream, PxTriangleMeshCookingResult::Enum* condition = NULL) const = 0; + + + /** + \brief Cooks and creates a triangle mesh and inserts it into PxPhysics. + + \note PxPhysicsInsertionCallback can be obtained through PxPhysics::getPhysicsInsertionCallback(). + + \param[in] desc The triangle mesh descriptor to read the mesh from. + \param[in] insertionCallback The insertion interface from PxPhysics. + \param[out] condition Result from triangle mesh cooking. + \return PxTriangleMesh pointer on success. + + @see cookTriangleMesh() setParams() PxPhysics.createTriangleMesh() PxPhysicsInsertionCallback + */ + virtual PxTriangleMesh* createTriangleMesh(const PxTriangleMeshDesc& desc, PxPhysicsInsertionCallback& insertionCallback, PxTriangleMeshCookingResult::Enum* condition = NULL) const = 0; + + /** + \brief Verifies if the triangle mesh is valid. Prints an error message for each inconsistency found. + + The following conditions are true for a valid triangle mesh: + 1. There are no duplicate vertices (within specified vertexWeldTolerance. See PxCookingParams::meshWeldTolerance) + 2. There are no large triangles (within specified PxTolerancesScale.) + + \param[in] desc The triangle mesh descriptor to read the mesh from. + + \return true if all the validity conditions hold, false otherwise. + + @see cookTriangleMesh() + */ + virtual bool validateTriangleMesh(const PxTriangleMeshDesc& desc) const = 0; + + + /** + \brief Cooks a convex mesh. The results are written to the stream. + + To create a triangle mesh object it is necessary to first 'cook' the mesh data into + a form which allows the SDK to perform efficient collision detection. + + cookConvexMesh() allows a mesh description to be cooked into a binary stream + suitable for loading and performing collision detection at runtime. + + \note The number of vertices and the number of convex polygons in a cooked convex mesh is limited to 255. + \note If those limits are exceeded in either the user-provided data or the final cooked mesh, an error is reported. + + \param[in] desc The convex mesh descriptor to read the mesh from. + \param[in] stream User stream to output the cooked data. + \param[out] condition Result from convex mesh cooking. + \return true on success. + + @see cookTriangleMesh() setParams() PxConvexMeshCookingResult::Enum + */ + virtual bool cookConvexMesh(const PxConvexMeshDesc& desc, PxOutputStream& stream, PxConvexMeshCookingResult::Enum* condition = NULL) const = 0; + + /** + \brief Cooks and creates a convex mesh and inserts it into PxPhysics. + + \note This method does the same as cookConvexMesh, but the produced convex mesh is not stored + into a stream but is directly inserted in PxPhysics. Use this method if you are unable to cook offline. + + \note PxPhysicsInsertionCallback can be obtained through PxPhysics::getPhysicsInsertionCallback(). + + \param[in] desc The convex mesh descriptor to read the mesh from. + \param[in] insertionCallback The insertion interface from PxPhysics. + \param[out] condition Result from convex mesh cooking. + \return PxConvexMesh pointer on success + + @see cookConvexMesh() setParams() PxPhysicsInsertionCallback + */ + virtual PxConvexMesh* createConvexMesh(const PxConvexMeshDesc& desc, PxPhysicsInsertionCallback& insertionCallback, PxConvexMeshCookingResult::Enum* condition = NULL) const = 0; + + /** + \brief Verifies if the convex mesh is valid. Prints an error message for each inconsistency found. + + The convex mesh descriptor must contain an already created convex mesh - the vertices, indices and polygons must be provided. + + \note This function should be used if PxConvexFlag::eDISABLE_MESH_VALIDATION is planned to be used in release builds. + + \param[in] desc The convex mesh descriptor to read the mesh from. + + \return true if all the validity conditions hold, false otherwise. + + @see cookConvexMesh() + */ + virtual bool validateConvexMesh(const PxConvexMeshDesc& desc) const = 0; + + + /** + \brief Computed hull polygons from given vertices and triangles. Polygons are needed for PxConvexMeshDesc rather than triangles. + + Please note that the resulting polygons may have different number of vertices. Some vertices may be removed. + The output vertices, indices and polygons must be used to construct a hull. + + The provided PxAllocatorCallback does allocate the out array's. It is the user responsibility to deallocated those + array's. + + \param[in] mesh Simple triangle mesh containing vertices and triangles used to compute polygons. + \param[in] inCallback Memory allocator for out array allocations. + \param[out] nbVerts Number of vertices used by polygons. + \param[out] vertices Vertices array used by polygons. + \param[out] nbIndices Number of indices used by polygons. + \param[out] indices Indices array used by polygons. + \param[out] nbPolygons Number of created polygons. + \param[out] hullPolygons Polygons array. + \return true on success + + @see cookConvexMesh() PxConvexFlags PxConvexMeshDesc PxSimpleTriangleMesh + */ + virtual bool computeHullPolygons(const PxSimpleTriangleMesh& mesh, PxAllocatorCallback& inCallback, PxU32& nbVerts, PxVec3*& vertices, + PxU32& nbIndices, PxU32*& indices, PxU32& nbPolygons, PxHullPolygon*& hullPolygons) const = 0; + + /** + \brief Cooks a heightfield. The results are written to the stream. + + To create a heightfield object there is an option to precompute some of calculations done while loading the heightfield data. + + cookHeightField() allows a heightfield description to be cooked into a binary stream + suitable for loading and performing collision detection at runtime. + + \param[in] desc The heightfield descriptor to read the HF from. + \param[in] stream User stream to output the cooked data. + \return true on success + + @see PxPhysics.createHeightField() + */ + virtual bool cookHeightField(const PxHeightFieldDesc& desc, PxOutputStream& stream) const = 0; + + /** + \brief Cooks and creates a heightfield mesh and inserts it into PxPhysics. + + \param[in] desc The heightfield descriptor to read the HF from. + \param[in] insertionCallback The insertion interface from PxPhysics. + \return PxHeightField pointer on success + + @see cookConvexMesh() setParams() PxPhysics.createTriangleMesh() PxPhysicsInsertionCallback + */ + virtual PxHeightField* createHeightField(const PxHeightFieldDesc& desc, PxPhysicsInsertionCallback& insertionCallback) const = 0; + + /** + \brief Cooks a bounding volume hierarchy structure. The results are written to the stream. + + cookBVHStructure() allows a BVH structure description to be cooked into a binary stream + suitable for loading and performing BVH detection at runtime. + + \param[in] desc The BVH structure descriptor. + \param[in] stream User stream to output the cooked data. + \return true on success. + + @see PxBVHStructure PxRigidActorExt::getRigidActorShapeLocalBoundsList + */ + virtual bool cookBVHStructure(const PxBVHStructureDesc& desc, PxOutputStream& stream) const = 0; + + /** + \brief Cooks and creates a bounding volume hierarchy structure and inserts it into PxPhysics. + + \note This method does the same as cookBVHStructure, but the produced BVH structure is not stored + into a stream but is directly inserted in PxPhysics. Use this method if you are unable to cook offline. + + \note PxPhysicsInsertionCallback can be obtained through PxPhysics::getPhysicsInsertionCallback(). + + \param[in] desc The BVH structure descriptor. + \param[in] insertionCallback The insertion interface from PxPhysics. + \return PxBVHStructure pointer on success + + @see cookBVHStructure() PxPhysicsInsertionCallback + */ + virtual PxBVHStructure* createBVHStructure(const PxBVHStructureDesc& desc, PxPhysicsInsertionCallback& insertionCallback) const = 0; +protected: + virtual ~PxCooking(){} +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** +\brief Create an instance of the cooking interface. + +Note that the foundation object is handled as an application-wide singleton in statically linked executables +and a DLL-wide singleton in dynamically linked executables. Therefore, if you are using the runtime SDK in the +same executable as cooking, you should pass the Physics's copy of foundation (acquired with +PxPhysics::getFoundation()) to the cooker. This will also ensure correct handling of memory for objects +passed from the cooker to the SDK. + +To use cooking in standalone mode, create an instance of the Foundation object with PxCreateCookingFoundation. +You should pass the same foundation object to all instances of the cooking interface. + +\param[in] version the SDK version number +\param[in] foundation the foundation object associated with this instance of the cooking interface. +\param[in] params the parameters for this instance of the cooking interface +\return true on success. +*/ +PX_C_EXPORT PX_PHYSX_COOKING_API physx::PxCooking* PX_CALL_CONV PxCreateCooking(physx::PxU32 version, + physx::PxFoundation& foundation, + const physx::PxCookingParams& params); + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/cooking/PxMidphaseDesc.h b/sources/PhysX/PhysX/include/cooking/PxMidphaseDesc.h new file mode 100644 index 00000000..fda59c99 --- /dev/null +++ b/sources/PhysX/PhysX/include/cooking/PxMidphaseDesc.h @@ -0,0 +1,119 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_MIDPHASE_DESC_H +#define PX_MIDPHASE_DESC_H +/** \addtogroup cooking +@{ +*/ + +#include "geometry/PxTriangleMesh.h" +#include "cooking/PxBVH33MidphaseDesc.h" +#include "cooking/PxBVH34MidphaseDesc.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** + +\brief Structure describing parameters affecting midphase mesh structure. + +@see PxCookingParams, PxBVH33MidphaseDesc, PxBVH34MidphaseDesc +*/ +class PxMidphaseDesc +{ +public: + PX_FORCE_INLINE PxMidphaseDesc() { setToDefault(PxMeshMidPhase::eBVH33); } + + /** + \brief Returns type of midphase mesh structure. + \return PxMeshMidPhase::Enum + + @see PxMeshMidPhase::Enum + */ + PX_FORCE_INLINE PxMeshMidPhase::Enum getType() const { return mType; } + + /** + \brief Midphase descriptors union + + @see PxBV33MidphaseDesc, PxBV34MidphaseDesc + */ + union { + PxBVH33MidphaseDesc mBVH33Desc; + PxBVH34MidphaseDesc mBVH34Desc; + }; + + /** + \brief Initialize the midphase mesh structure descriptor + \param[in] type Midphase mesh structure descriptor + + @see PxBV33MidphaseDesc, PxBV34MidphaseDesc + */ + void setToDefault(PxMeshMidPhase::Enum type) + { + mType = type; + if(type==PxMeshMidPhase::eBVH33) + mBVH33Desc.setToDefault(); + else if(type==PxMeshMidPhase::eBVH34) + mBVH34Desc.setToDefault(); + } + + /** + \brief Returns true if the descriptor is valid. + \return true if the current settings are valid. + */ + bool isValid() const + { + if(mType==PxMeshMidPhase::eBVH33) + return mBVH33Desc.isValid(); + else if(mType==PxMeshMidPhase::eBVH34) + return mBVH34Desc.isValid(); + return false; + } + + PX_FORCE_INLINE PxMidphaseDesc& operator=(PxMeshMidPhase::Enum descType) + { + setToDefault(descType); + return *this; + } + +protected: + PxMeshMidPhase::Enum mType; +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + + + /** @} */ +#endif // PX_MIDPHASE_DESC_UNION_H diff --git a/sources/PhysX/PhysX/include/cooking/PxTriangleMeshDesc.h b/sources/PhysX/PhysX/include/cooking/PxTriangleMeshDesc.h new file mode 100644 index 00000000..d3b8ea6d --- /dev/null +++ b/sources/PhysX/PhysX/include/cooking/PxTriangleMeshDesc.h @@ -0,0 +1,120 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_COLLISION_NXTRIANGLEMESHDESC +#define PX_COLLISION_NXTRIANGLEMESHDESC +/** \addtogroup cooking +@{ +*/ + +#include "PxPhysXConfig.h" +#include "geometry/PxSimpleTriangleMesh.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief Descriptor class for #PxTriangleMesh. + +Note that this class is derived from PxSimpleTriangleMesh which contains the members that describe the basic mesh. +The mesh data is *copied* when an PxTriangleMesh object is created from this descriptor. After the call the +user may discard the triangle data. + +@see PxTriangleMesh PxTriangleMeshGeometry PxShape +*/ +class PxTriangleMeshDesc : public PxSimpleTriangleMesh +{ +public: + + /** + Optional pointer to first material index, or NULL. There are PxSimpleTriangleMesh::numTriangles indices in total. + Caller may add materialIndexStride bytes to the pointer to access the next triangle. + + When a triangle mesh collides with another object, a material is required at the collision point. + If materialIndices is NULL, then the material of the PxShape instance is used. + Otherwise, if the point of contact is on a triangle with index i, then the material index is determined as: + PxMaterialTableIndex index = *(PxMaterialTableIndex *)(((PxU8*)materialIndices) + materialIndexStride * i); + + If the contact point falls on a vertex or an edge, a triangle adjacent to the vertex or edge is selected, and its index + used to look up a material. The selection is arbitrary but consistent over time. + + Default: NULL + + @see materialIndexStride + */ + PxTypedStridedData materialIndices; + + /** + \brief Constructor sets to default. + */ + PX_INLINE PxTriangleMeshDesc(); + + /** + \brief (re)sets the structure to the default. + */ + PX_INLINE void setToDefault(); + + /** + \brief Returns true if the descriptor is valid. + \return true if the current settings are valid + */ + PX_INLINE bool isValid() const; +}; + +PX_INLINE PxTriangleMeshDesc::PxTriangleMeshDesc() //constructor sets to default +{ + PxSimpleTriangleMesh::setToDefault(); +} + +PX_INLINE void PxTriangleMeshDesc::setToDefault() +{ + *this = PxTriangleMeshDesc(); +} + +PX_INLINE bool PxTriangleMeshDesc::isValid() const +{ + if(points.count < 3) //at least 1 trig's worth of points + return false; + if ((!triangles.data) && (points.count%3)) // Non-indexed mesh => we must ensure the geometry defines an implicit number of triangles // i.e. numVertices can't be divided by 3 + return false; + //add more validity checks here + if (materialIndices.data && materialIndices.stride < sizeof(PxMaterialTableIndex)) + return false; + return PxSimpleTriangleMesh::isValid(); +} + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/cooking/Pxc.h b/sources/PhysX/PhysX/include/cooking/Pxc.h new file mode 100644 index 00000000..ab28adf0 --- /dev/null +++ b/sources/PhysX/PhysX/include/cooking/Pxc.h @@ -0,0 +1,57 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_COOKING_NX +#define PX_COOKING_NX + +#include "foundation/Px.h" + +// define API function declaration +#if !defined PX_PHYSX_STATIC_LIB + #if (PX_WINDOWS_FAMILY || PX_XBOXONE || PX_PS4) + #if defined PX_PHYSX_COOKING_EXPORTS + #define PX_PHYSX_COOKING_API __declspec(dllexport) + #else + #define PX_PHYSX_COOKING_API __declspec(dllimport) + #endif + #elif PX_UNIX_FAMILY + #define PX_PHYSX_COOKING_API PX_UNIX_EXPORT + #endif +#endif + +#if !defined(PX_PHYSX_COOKING_API) + #define PX_PHYSX_COOKING_API +#endif + +#ifndef PX_C_EXPORT + #define PX_C_EXPORT extern "C" +#endif + +#endif diff --git a/sources/PhysX/PhysX/include/cudamanager/PxCudaContextManager.h b/sources/PhysX/PhysX/include/cudamanager/PxCudaContextManager.h new file mode 100644 index 00000000..dbf6a021 --- /dev/null +++ b/sources/PhysX/PhysX/include/cudamanager/PxCudaContextManager.h @@ -0,0 +1,399 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. + + +#ifndef PXCUDACONTEXTMANAGER_PXCUDACONTEXTMANAGER_H +#define PXCUDACONTEXTMANAGER_PXCUDACONTEXTMANAGER_H + +#include "foundation/PxPreprocessor.h" + +#if PX_SUPPORT_GPU_PHYSX + +#include "foundation/PxSimpleTypes.h" +#include "foundation/PxErrorCallback.h" +#include "foundation/PxFlags.h" +#include "task/PxTaskDefine.h" +#include "cudamanager/PxCudaMemoryManager.h" + +/* Forward decl to avoid inclusion of cuda.h */ +typedef struct CUctx_st *CUcontext; +typedef struct CUgraphicsResource_st *CUgraphicsResource; +typedef int CUdevice; + +namespace physx +{ + +/** \brief Possible graphic/CUDA interoperability modes for context */ +struct PxCudaInteropMode +{ + /** + * \brief Possible graphic/CUDA interoperability modes for context + */ + enum Enum + { + NO_INTEROP = 0, + D3D10_INTEROP, + D3D11_INTEROP, + OGL_INTEROP, + + COUNT + }; +}; + +struct PxCudaInteropRegisterFlag +{ + enum Enum + { + eNONE = 0x00, + eREAD_ONLY = 0x01, + eWRITE_DISCARD = 0x02, + eSURFACE_LDST = 0x04, + eTEXTURE_GATHER = 0x08 + }; +}; + +/** +\brief collection of set bits defined in NxCudaInteropRegisterFlag. + +@see NxCudaInteropRegisterFlag +*/ +typedef PxFlags PxCudaInteropRegisterFlags; +PX_FLAGS_OPERATORS(PxCudaInteropRegisterFlag::Enum, uint32_t) + +//! \brief Descriptor used to create a PxCudaContextManager +class PxCudaContextManagerDesc +{ +public: + /** + * \brief The CUDA context to manage + * + * If left NULL, the PxCudaContextManager will create a new context. If + * graphicsDevice is also not NULL, this new CUDA context will be bound to + * that graphics device, enabling the use of CUDA/Graphics interop features. + * + * If ctx is not NULL, the specified context must be applied to the thread + * that is allocating the PxCudaContextManager at creation time (aka, it + * cannot be popped). The PxCudaContextManager will take ownership of the + * context until the manager is released. All access to the context must be + * gated by lock acquisition. + * + * If the user provides a context for the PxCudaContextManager, the context + * _must_ have either been created on the GPU ordinal returned by + * PxGetSuggestedCudaDeviceOrdinal() or on your graphics device. + * + * It is perfectly acceptable to allocate device or host pinned memory from + * the context outside the scope of the PxCudaMemoryManager, so long as you + * manage its eventual cleanup. + */ + CUcontext *ctx; + + /** + * \brief D3D device pointer or OpenGl context handle + * + * Only applicable when ctx is NULL, thus forcing a new context to be + * created. In that case, the created context will be bound to this + * graphics device. + */ + void *graphicsDevice; + +#if PX_SUPPORT_GPU_PHYSX + /** + * \brief Application-specific GUID + * + * If your application employs PhysX modules that use CUDA you need to use a GUID + * so that patches for new architectures can be released for your game.You can obtain a GUID for your + * application from Nvidia. + */ + const char* appGUID; +#endif + /** + * \brief The CUDA/Graphics interop mode of this context + * + * If ctx is NULL, this value describes the nature of the graphicsDevice + * pointer provided by the user. Else it describes the nature of the + * context provided by the user. + */ + PxCudaInteropMode::Enum interopMode; + + + /** + * \brief Size of persistent memory + * + * This memory is allocated up front and stays allocated until the + * PxCudaContextManager is released. Size is in bytes, has to be power of two + * and bigger than the page size. Set to 0 to only use dynamic pages. + * + * Note: On Vista O/S and above, there is a per-memory allocation overhead + * to every CUDA work submission, so we recommend that you carefully tune + * this initial base memory size to closely approximate the amount of + * memory your application will consume. + + Note: This is currently not used by PxSceneFlag::eENABLE_GPU_DYNAMICS. Memory allocation properties are configured + for GPU rigid bodies using PxSceneDesc::gpuDynamicsConfig. + */ + uint32_t memoryBaseSize[PxCudaBufferMemorySpace::COUNT]; + + /** + * \brief Size of memory pages + * + * The memory manager will dynamically grow and shrink in blocks multiple of + * this page size. Size has to be power of two and bigger than 0. + + Note: This is currently not used by PxSceneFlag::eENABLE_GPU_DYNAMICS. Memory allocation properties are configured + for GPU rigid bodies using PxSceneDesc::gpuDynamicsConfig. + */ + uint32_t memoryPageSize[PxCudaBufferMemorySpace::COUNT]; + + /** + * \brief Maximum size of memory that the memory manager will allocate + + Note: This is currently not used by PxSceneFlag::eENABLE_GPU_DYNAMICS. Memory allocation properties are configured + for GPU rigid bodies using PxSceneDesc::gpuDynamicsConfig. + */ + uint32_t maxMemorySize[PxCudaBufferMemorySpace::COUNT]; + + PX_INLINE PxCudaContextManagerDesc() + { + ctx = NULL; + interopMode = PxCudaInteropMode::NO_INTEROP; + graphicsDevice = 0; +#if PX_SUPPORT_GPU_PHYSX + appGUID = NULL; +#endif + for(uint32_t i = 0; i < PxCudaBufferMemorySpace::COUNT; i++) + { + memoryBaseSize[i] = 0; + memoryPageSize[i] = 2 * 1024*1024; + maxMemorySize[i] = UINT32_MAX; + } + } +}; + + +/** + * \brief Manages memory, thread locks, and task scheduling for a CUDA context + * + * A PxCudaContextManager manages access to a single CUDA context, allowing it to + * be shared between multiple scenes. Memory allocations are dynamic: starting + * with an initial heap size and growing on demand by a configurable page size. + * The context must be acquired from the manager before using any CUDA APIs. + * + * The PxCudaContextManager is based on the CUDA driver API and explictly does not + * support the CUDA runtime API (aka, CUDART). + */ +class PxCudaContextManager +{ +public: + /** + * \brief Acquire the CUDA context for the current thread + * + * Acquisitions are allowed to be recursive within a single thread. + * You can acquire the context multiple times so long as you release + * it the same count. + * + * The context must be acquired before using most CUDA functions. + */ + virtual void acquireContext() = 0; + + /** + * \brief Release the CUDA context from the current thread + * + * The CUDA context should be released as soon as practically + * possible, to allow other CPU threads to work efficiently. + */ + virtual void releaseContext() = 0; + + /** + * \brief Return the CUcontext + */ + virtual CUcontext getContext() = 0; + + /** + * \brief Return the PxCudaMemoryManager instance associated with this + * CUDA context + * Note: This is currently not used by PxSceneFlag::eENABLE_GPU_DYNAMICS. Memory allocation properties are configured + * for GPU rigid bodies using PxSceneDesc::gpuDynamicsConfig. + */ + virtual PxCudaMemoryManager *getMemoryManager() = 0; + + /** + * \brief Context manager has a valid CUDA context + * + * This method should be called after creating a PxCudaContextManager, + * especially if the manager was responsible for allocating its own + * CUDA context (desc.ctx == NULL). + */ + virtual bool contextIsValid() const = 0; + + /* Query CUDA context and device properties, without acquiring context */ + + virtual bool supportsArchSM10() const = 0; //!< G80 + virtual bool supportsArchSM11() const = 0; //!< G92 + virtual bool supportsArchSM12() const = 0; //!< GT200 + virtual bool supportsArchSM13() const = 0; //!< GT260 + virtual bool supportsArchSM20() const = 0; //!< GF100 + virtual bool supportsArchSM30() const = 0; //!< GK100 + virtual bool supportsArchSM35() const = 0; //!< GK110 + virtual bool supportsArchSM50() const = 0; //!< GM100 + virtual bool supportsArchSM52() const = 0; //!< GM200 + virtual bool supportsArchSM60() const = 0; //!< GP100 + virtual bool isIntegrated() const = 0; //!< true if GPU is an integrated (MCP) part + virtual bool canMapHostMemory() const = 0; //!< true if GPU map host memory to GPU (0-copy) + virtual int getDriverVersion() const = 0; //!< returns cached value of cuGetDriverVersion() + virtual size_t getDeviceTotalMemBytes() const = 0; //!< returns cached value of device memory size + virtual int getMultiprocessorCount() const = 0; //!< returns cache value of SM unit count + virtual unsigned int getClockRate() const = 0; //!< returns cached value of SM clock frequency + virtual int getSharedMemPerBlock() const = 0; //!< returns total amount of shared memory available per block in bytes + virtual int getSharedMemPerMultiprocessor() const = 0; //!< returns total amount of shared memory available per multiprocessor in bytes + virtual unsigned int getMaxThreadsPerBlock() const = 0; //!< returns the maximum number of threads per block + virtual const char *getDeviceName() const = 0; //!< returns device name retrieved from driver + virtual CUdevice getDevice() const = 0; //!< returns device handle retrieved from driver + virtual PxCudaInteropMode::Enum getInteropMode() const = 0; //!< interop mode the context was created with + + virtual void setUsingConcurrentStreams(bool) = 0; //!< turn on/off using concurrent streams for GPU work + virtual bool getUsingConcurrentStreams() const = 0; //!< true if GPU work can run in concurrent streams + /* End query methods that don't require context to be acquired */ + + /** + * \brief Register a rendering resource with CUDA + * + * This function is called to register render resources (allocated + * from OpenGL) with CUDA so that the memory may be shared + * between the two systems. This is only required for render + * resources that are designed for interop use. In APEX, each + * render resource descriptor that could support interop has a + * 'registerInCUDA' boolean variable. + * + * The function must be called again any time your graphics device + * is reset, to re-register the resource. + * + * Returns true if the registration succeeded. A registered + * resource must be unregistered before it can be released. + * + * \param resource [OUT] the handle to the resource that can be used with CUDA + * \param buffer [IN] GLuint buffer index to be mapped to cuda + * \param flags [IN] cuda interop registration flags + */ + virtual bool registerResourceInCudaGL(CUgraphicsResource &resource, uint32_t buffer, PxCudaInteropRegisterFlags flags = PxCudaInteropRegisterFlags()) = 0; + + /** + * \brief Register a rendering resource with CUDA + * + * This function is called to register render resources (allocated + * from Direct3D) with CUDA so that the memory may be shared + * between the two systems. This is only required for render + * resources that are designed for interop use. In APEX, each + * render resource descriptor that could support interop has a + * 'registerInCUDA' boolean variable. + * + * The function must be called again any time your graphics device + * is reset, to re-register the resource. + * + * Returns true if the registration succeeded. A registered + * resource must be unregistered before it can be released. + * + * \param resource [OUT] the handle to the resource that can be used with CUDA + * \param resourcePointer [IN] A pointer to either IDirect3DResource9, or ID3D10Device, or ID3D11Resource to be registered. + * \param flags [IN] cuda interop registration flags + */ + virtual bool registerResourceInCudaD3D(CUgraphicsResource &resource, void *resourcePointer, PxCudaInteropRegisterFlags flags = PxCudaInteropRegisterFlags()) = 0; + + /** + * \brief Unregister a rendering resource with CUDA + * + * If a render resource was successfully registered with CUDA using + * the registerResourceInCuda***() methods, this function must be called + * to unregister the resource before the it can be released. + */ + virtual bool unregisterResourceInCuda(CUgraphicsResource resource) = 0; + + /** + * \brief Determine if the user has configured a dedicated PhysX GPU in the NV Control Panel + * \note If using CUDA Interop, this will always return false + * \returns 1 if there is a dedicated GPU + * 0 if there is NOT a dedicated GPU + * -1 if the routine is not implemented + */ + virtual int usingDedicatedGPU() const = 0; + + /** + * \brief Release the PxCudaContextManager + * + * When the manager instance is released, it also releases its + * PxCudaMemoryManager. Before the memory manager is released, it + * frees all allocated memory pages. If the PxCudaContextManager + * created the CUDA context it was responsible for, it also frees + * that context. + * + * Do not release the PxCudaContextManager if there are any scenes + * using it. Those scenes must be released first. + * + */ + virtual void release() = 0; + +protected: + + /** + * \brief protected destructor, use release() method + */ + virtual ~PxCudaContextManager() {} +}; + +/** + * \brief Convenience class for holding CUDA lock within a scope + */ +class PxScopedCudaLock +{ +public: + /** + * \brief ScopedCudaLock constructor + */ + PxScopedCudaLock(PxCudaContextManager& ctx) : mCtx(&ctx) + { + mCtx->acquireContext(); + } + + /** + * \brief ScopedCudaLock destructor + */ + ~PxScopedCudaLock() + { + mCtx->releaseContext(); + } + +protected: + + /** + * \brief CUDA context manager pointer (initialized in the constructor) + */ + PxCudaContextManager* mCtx; +}; + +} // end physx namespace + +#endif // PX_SUPPORT_GPU_PHYSX +#endif // PXCUDACONTEXTMANAGER_PXCUDACONTEXTMANAGER_H diff --git a/sources/PhysX/PhysX/include/cudamanager/PxCudaMemoryManager.h b/sources/PhysX/PhysX/include/cudamanager/PxCudaMemoryManager.h new file mode 100644 index 00000000..83dc2cce --- /dev/null +++ b/sources/PhysX/PhysX/include/cudamanager/PxCudaMemoryManager.h @@ -0,0 +1,281 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. + +#ifndef PXCUDACONTEXTMANAGER_PXCUDAMEMORYMANAGER_H +#define PXCUDACONTEXTMANAGER_PXCUDAMEMORYMANAGER_H + +#include "foundation/PxPreprocessor.h" + +#if PX_SUPPORT_GPU_PHYSX + +#include "task/PxTaskDefine.h" + +// some macros to keep the source code more readable +#define PX_ALLOC_INFO(name, ID) __FILE__, __LINE__, name, physx::PxAllocId::ID +#define PX_ALLOC_INFO_PARAMS_DECL(p0, p1, p2, p3) const char* file = p0, int line = p1, const char* allocName = p2, physx::PxAllocId::Enum allocId = physx::PxAllocId::p3 +#define PX_ALLOC_INFO_PARAMS_DEF() const char* file, int line, const char* allocName, physx::PxAllocId::Enum allocId +#define PX_ALLOC_INFO_PARAMS_INPUT() file, line, allocName, allocId +#define PX_ALLOC_INFO_PARAMS_INPUT_INFO(info) info.getFileName(), info.getLine(), info.getAllocName(), info.getAllocId() + +#ifndef NULL // don't want to include +#define NULL 0 +#endif + +namespace physx +{ + +PX_PUSH_PACK_DEFAULT + +/** \brief ID of the Feature which owns/allocated memory from the heap + * + * Maximum of 64k IDs allowed. + */ +struct PxAllocId +{ + /** + * \brief ID of the Feature which owns/allocated memory from the heap + */ + enum Enum + { + UNASSIGNED, //!< default + APEX, //!< APEX stuff not further classified + PARTICLES, //!< all particle related + GPU_UTIL, //!< e.g. RadixSort (used in SPH and deformable self collision) + CLOTH, //!< all cloth related + NUM_IDS //!< number of IDs, be aware that ApexHeapStats contains PxAllocIdStats[NUM_IDS] + }; +}; + +/// \brief memory type managed by a heap +struct PxCudaBufferMemorySpace +{ + /** + * \brief memory type managed by a heap + */ + enum Enum + { + T_GPU, + T_PINNED_HOST, + T_WRITE_COMBINED, + T_HOST, + COUNT + }; +}; + +/// \brief class to track allocation statistics, see PxgMirrored +class PxAllocInfo +{ +public: + /** + * \brief AllocInfo default constructor + */ + PxAllocInfo() {} + + /** + * \brief AllocInfo constructor that initializes all of the members + */ + PxAllocInfo(const char* file, int line, const char* allocName, PxAllocId::Enum allocId) + : mFileName(file) + , mLine(line) + , mAllocName(allocName) + , mAllocId(allocId) + {} + + /// \brief get the allocation file name + inline const char* getFileName() const + { + return mFileName; + } + + /// \brief get the allocation line + inline int getLine() const + { + return mLine; + } + + /// \brief get the allocation name + inline const char* getAllocName() const + { + return mAllocName; + } + + /// \brief get the allocation ID + inline PxAllocId::Enum getAllocId() const + { + return mAllocId; + } + +private: + const char* mFileName; + int mLine; + const char* mAllocName; + PxAllocId::Enum mAllocId; +}; + +/// \brief statistics collected per AllocationId by HeapManager. +struct PxAllocIdStats +{ + size_t size; //!< currently allocated memory by this ID + size_t maxSize; //!< max allocated memory by this ID + size_t elements; //!< number of current allocations by this ID + size_t maxElements; //!< max number of allocations by this ID +}; + +class PxCudaMemoryManager; +typedef size_t PxCudaBufferPtr; + +/// \brief Hint flag to tell how the buffer will be used +struct PxCudaBufferFlags +{ +/// \brief Enumerations for the hint flag to tell how the buffer will be used + enum Enum + { + F_READ = (1 << 0), + F_WRITE = (1 << 1), + F_READ_WRITE = F_READ | F_WRITE + }; +}; + + +/// \brief Memory statistics struct returned by CudaMemMgr::getStats() +struct PxCudaMemoryManagerStats +{ + + size_t heapSize; //!< Size of all pages allocated for this memory type (allocated + free). + size_t totalAllocated; //!< Size occupied by the current allocations. + size_t maxAllocated; //!< High water mark of allocations since the SDK was created. + PxAllocIdStats allocIdStats[PxAllocId::NUM_IDS]; //!< Stats for each allocation ID, see PxAllocIdStats +}; + + +/// \brief Buffer type: made of hint flags and the memory space (Device Memory, Pinned Host Memory, ...) +struct PxCudaBufferType +{ + /// \brief PxCudaBufferType copy constructor + PX_INLINE PxCudaBufferType(const PxCudaBufferType& t) + : memorySpace(t.memorySpace) + , flags(t.flags) + {} + + /// \brief PxCudaBufferType constructor to explicitely assign members + PX_INLINE PxCudaBufferType(PxCudaBufferMemorySpace::Enum _memSpace, PxCudaBufferFlags::Enum _flags) + : memorySpace(_memSpace) + , flags(_flags) + {} + + PxCudaBufferMemorySpace::Enum memorySpace; //!< specifies which memory space for the buffer + PxCudaBufferFlags::Enum flags; //!< specifies the usage flags for the buffer +}; + + +/// \brief Buffer which keeps informations about allocated piece of memory. +class PxCudaBuffer +{ +public: + /// Retrieves the manager over which the buffer was allocated. + virtual PxCudaMemoryManager* getCudaMemoryManager() const = 0; + + /// Releases the buffer and the memory it used, returns true if successful. + virtual bool free() = 0; + + /// Realloc memory. Use to shrink or resize the allocated chunk of memory of this buffer. + /// Returns true if successful. Fails if the operation would change the address and need a memcopy. + /// In that case the user has to allocate, copy and free the memory with separate steps. + /// Realloc to size 0 always returns false and doesn't change the state. + virtual bool realloc(size_t size, PX_ALLOC_INFO_PARAMS_DECL(NULL, 0, NULL, UNASSIGNED)) = 0; + + /// Returns the type of the allocated memory. + virtual const PxCudaBufferType& getType() const = 0; + + /// Returns the pointer to the allocated memory. + virtual PxCudaBufferPtr getPtr() const = 0; + + /// Returns the size of the allocated memory. + virtual size_t getSize() const = 0; + +protected: + /// \brief protected destructor + virtual ~PxCudaBuffer() {} +}; + + +/// \brief Allocator class for different kinds of CUDA related memory. +class PxCudaMemoryManager +{ +public: + /// Allocate memory of given type and size. Returns a CudaBuffer if successful. Returns NULL if failed. + virtual PxCudaBuffer* alloc(const PxCudaBufferType& type, size_t size, PX_ALLOC_INFO_PARAMS_DECL(NULL, 0, NULL, UNASSIGNED)) = 0; + + /// Basic heap allocator without PxCudaBuffer + virtual PxCudaBufferPtr alloc(PxCudaBufferMemorySpace::Enum memorySpace, size_t size, PX_ALLOC_INFO_PARAMS_DECL(NULL, 0, NULL, UNASSIGNED)) = 0; + + /// Basic heap deallocator without PxCudaBuffer + virtual bool free(PxCudaBufferMemorySpace::Enum memorySpace, PxCudaBufferPtr addr) = 0; + + /// Basic heap realloc without PxCudaBuffer + virtual bool realloc(PxCudaBufferMemorySpace::Enum memorySpace, PxCudaBufferPtr addr, size_t size, PX_ALLOC_INFO_PARAMS_DECL(NULL, 0, NULL, UNASSIGNED)) = 0; + + /// Retrieve stats for the memory of given type. See PxCudaMemoryManagerStats. + virtual void getStats(const PxCudaBufferType& type, PxCudaMemoryManagerStats& outStats) = 0; + + /// Ensure that a given amount of free memory is available. Triggers CUDA allocations in size of (2^n * pageSize) if necessary. + /// Returns false if page allocations failed. + virtual bool reserve(const PxCudaBufferType& type, size_t size) = 0; + + /// Set the page size. The managed memory grows by blocks 2^n * pageSize. Page allocations trigger CUDA driver allocations, + /// so the page size should be reasonably big. Returns false if input size was invalid, i.e. not power of two. + /// Default is 2 MB. + virtual bool setPageSize(const PxCudaBufferType& type, size_t size) = 0; + + /// Set the upper limit until which pages of a given memory type can be allocated. + /// Reducing the max when it is already hit does not shrink the memory until it is deallocated by releasing the buffers which own the memory. + virtual bool setMaxMemorySize(const PxCudaBufferType& type, size_t size) = 0; + + /// Returns the base size. The base memory block stays persistently allocated over the SDKs life time. + virtual size_t getBaseSize(const PxCudaBufferType& type) = 0; + + /// Returns the currently set page size. The memory grows and shrinks in blocks of size (2^n pageSize) + virtual size_t getPageSize(const PxCudaBufferType& type) = 0; + + /// Returns the upper limit until which the manager is allowed to allocate additional pages from the CUDA driver. + virtual size_t getMaxMemorySize(const PxCudaBufferType& type) = 0; + + /// Get device mapped pinned host mem ptr. Operation only valid for memory space PxCudaBufferMemorySpace::T_PINNED_HOST. + virtual PxCudaBufferPtr getMappedPinnedPtr(PxCudaBufferPtr hostPtr) = 0; + +protected: + /// \brief protected destructor + virtual ~PxCudaMemoryManager() {} +}; + +PX_POP_PACK + + +} // end physx namespace + +#endif // PX_SUPPORT_GPU_PHYSX +#endif // PXCUDACONTEXTMANAGER_PXCUDAMEMORYMANAGER_H diff --git a/sources/PhysX/PhysX/include/extensions/PxBinaryConverter.h b/sources/PhysX/PhysX/include/extensions/PxBinaryConverter.h new file mode 100644 index 00000000..ec790a72 --- /dev/null +++ b/sources/PhysX/PhysX/include/extensions/PxBinaryConverter.h @@ -0,0 +1,134 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_BINARY_CONVERTER_H +#define PX_BINARY_CONVERTER_H +/** \addtogroup extensions +@{ +*/ + +#include "common/PxPhysXCommonConfig.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +struct PxConverterReportMode +{ + enum Enum + { + eNONE, //!< Silent mode. If enabled, no information is sent to the error stream. + eNORMAL, //!< Normal mode. If enabled, only important information is sent to the error stream. + eVERBOSE //!< Verbose mode. If enabled, detailed information is sent to the error stream. + }; +}; + + +/** +\brief Binary converter for serialized streams. + +The binary converter class is targeted at converting binary streams from authoring platforms, +such as windows, osx or linux to any game runtime platform supported by PhysX. Particularly +it is currently not supported to run the converter on a platforms that has an endian mismatch +with the platform corresponding to the source binary file and source meta data. + +If you want to use multiple threads for batch conversions, please create one instance +of this class for each thread. + +@see PxSerialization.createBinaryConverter +*/ +class PxBinaryConverter +{ +public: + + /** + \brief Releases binary converter + */ + virtual void release() = 0; + + /** + \brief Sets desired report mode. + + \param[in] mode Report mode + */ + virtual void setReportMode(PxConverterReportMode::Enum mode) = 0; + + /** + \brief Setups source and target meta-data streams + + The source meta data provided needs to have the same endianness as the platform the converter is run on. + The meta data needs to be set before calling the conversion method. + + \param[in] srcMetaData Source platform's meta-data stream + \param[in] dstMetaData Target platform's meta-data stream + + \return True if success + + @see PxSerialization::dumpBinaryMetaData + */ + virtual bool setMetaData(PxInputStream& srcMetaData, PxInputStream& dstMetaData) = 0; + + /** + \brief Test utility function to compare two sets of meta data. + + The meta data needs to be set before calling the compareMetaData method. + This method will issue PxErrorCode::eDEBUG_INFO messages if mismatches are encountered. + + \return True if meta data is equivalend + */ + virtual bool compareMetaData() const = 0; + + /** + \brief Converts binary stream from source platform to target platform + + The converter needs to be configured with source and destination meta data before calling the conversion method. + The source meta data needs to correspond to the same platform as the source binary data. + + \param[in] srcStream Source stream + \param[in] srcSize Number of bytes to convert + \param[in] targetStream Target stream + + \return True if success + */ + virtual bool convert(PxInputStream& srcStream, PxU32 srcSize, PxOutputStream& targetStream) = 0; + + +protected: + PxBinaryConverter() {} + virtual ~PxBinaryConverter() {} +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/extensions/PxBroadPhaseExt.h b/sources/PhysX/PhysX/include/extensions/PxBroadPhaseExt.h new file mode 100644 index 00000000..d5562192 --- /dev/null +++ b/sources/PhysX/PhysX/include/extensions/PxBroadPhaseExt.h @@ -0,0 +1,75 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_EXTENSIONS_BROAD_PHASE_H +#define PX_PHYSICS_EXTENSIONS_BROAD_PHASE_H +/** \addtogroup extensions + @{ +*/ + +#include "PxPhysXConfig.h" +#include "common/PxPhysXCommonConfig.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxBroadPhaseExt +{ +public: + + /** + \brief Creates regions for PxSceneDesc, from a global box. + + This helper simply subdivides the given global box into a 2D grid of smaller boxes. Each one of those smaller boxes + is a region of interest for the broadphase. There are nbSubdiv*nbSubdiv regions in the 2D grid. The function does not + subdivide along the given up axis. + + This is the simplest setup one can use with PxBroadPhaseType::eMBP. A more sophisticated setup would try to cover + the game world with a non-uniform set of regions (i.e. not just a grid). + + \param[out] regions Regions computed from the input global box + \param[in] globalBounds World-space box covering the game world + \param[in] nbSubdiv Grid subdivision level. The function will create nbSubdiv*nbSubdiv regions. + \param[in] upAxis Up axis (0 for X, 1 for Y, 2 for Z). + \return number of regions written out to the 'regions' array + + @see PxSceneDesc PxBroadPhaseType + */ + static PxU32 createRegionsFromWorldBounds(PxBounds3* regions, const PxBounds3& globalBounds, PxU32 nbSubdiv, PxU32 upAxis=1); +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/extensions/PxCollectionExt.h b/sources/PhysX/PhysX/include/extensions/PxCollectionExt.h new file mode 100644 index 00000000..85e8bee4 --- /dev/null +++ b/sources/PhysX/PhysX/include/extensions/PxCollectionExt.h @@ -0,0 +1,119 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_COLLECTION_EXT_H +#define PX_COLLECTION_EXT_H +/** \addtogroup extensions +@{ +*/ + +#include "PxPhysXConfig.h" +#include "common/PxCollection.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + + class PxCollectionExt + { + public: + /** + \brief Removes and releases all object from a collection. + + The Collection itself is not released. + + If the releaseExclusiveShapes flag is not set to true, release() will not be called on exclusive shapes. + + It is assumed that the application holds a reference to each of the objects in the collection, with the exception of objects that are not releasable + (PxBase::isReleasable()). In general, objects that violate this assumption need to be removed from the collection prior to calling releaseObjects. + + \note when a shape is created with PxRigidActor::createShape() or PxRigidActorExt::createExclusiveShape(), the only counted reference is held by the actor. + If such a shape and its actor are present in the collection, the reference count will be decremented once when the actor is released, and once when the + shape is released, resulting in undefined behavior. Shape reference counts can be incremented with PxShape::acquireReference(). + + \param[in] collection to remove and release all object from. + \param[in] releaseExclusiveShapes if this parameter is set to false, release() will not be called on exclusive shapes. + */ + static void releaseObjects(PxCollection& collection, bool releaseExclusiveShapes = true); + + /** + \brief Removes objects of a given type from a collection, potentially adding them to another collection. + + \param[in,out] collection Collection from which objects are removed + \param[in] concreteType PxConcreteType of sdk objects that should be removed + \param[in,out] to Optional collection to which the removed objects are added + + @see PxCollection, PxConcreteType + */ + static void remove(PxCollection& collection, PxType concreteType, PxCollection* to = NULL); + + + /** + \brief Collects all objects in PxPhysics that are shareable across multiple scenes. + + This function creates a new collection from all objects that are shareable across multiple + scenes. Instances of the following types are included: PxConvexMesh, PxTriangleMesh, + PxHeightField, PxShape and PxMaterial. + + This is a helper function to ease the creation of collections for serialization. + + \param[in] physics The physics SDK instance from which objects are collected. See #PxPhysics + \return Collection to which objects are added. See #PxCollection + + @see PxCollection, PxPhysics + */ + static PxCollection* createCollection(PxPhysics& physics); + + /** + \brief Collects all objects from a PxScene. + + This function creates a new collection from all objects that where added to the specified + PxScene. Instances of the following types are included: PxActor, PxAggregate, + PxArticulation and PxJoint (other PxConstraint types are not included). + + This is a helper function to ease the creation of collections for serialization. + The function PxSerialization.complete() can be used to complete the collection with required objects prior to + serialization. + + \param[in] scene The PxScene instance from which objects are collected. See #PxScene + \return Collection to which objects are added. See #PxCollection + + @see PxCollection, PxScene, PxSerialization.complete() + */ + static PxCollection* createCollection(PxScene& scene); + }; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/extensions/PxConstraintExt.h b/sources/PhysX/PhysX/include/extensions/PxConstraintExt.h new file mode 100644 index 00000000..6c7a916b --- /dev/null +++ b/sources/PhysX/PhysX/include/extensions/PxConstraintExt.h @@ -0,0 +1,70 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_EXTENSIONS_CONSTRAINT_H +#define PX_PHYSICS_EXTENSIONS_CONSTRAINT_H + +#include "foundation/PxPreprocessor.h" + +/** \addtogroup extensions + @{ +*/ + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief Unique identifiers for extensions classes which implement a constraint based on PxConstraint. + +\note Users which want to create their own custom constraint types should choose an ID larger or equal to eNEXT_FREE_ID +and not eINVALID_ID. + +@see PxConstraint PxSimulationEventCallback.onConstraintBreak() +*/ +struct PxConstraintExtIDs +{ + enum Enum + { + eJOINT, + eVEHICLE_SUSP_LIMIT, + eVEHICLE_STICKY_TYRE, + eNEXT_FREE_ID, + eINVALID_ID = 0x7fffffff + }; +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/extensions/PxContactJoint.h b/sources/PhysX/PhysX/include/extensions/PxContactJoint.h new file mode 100644 index 00000000..b3f149b7 --- /dev/null +++ b/sources/PhysX/PhysX/include/extensions/PxContactJoint.h @@ -0,0 +1,168 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_CONTACTJOINT_H +#define PX_CONTACTJOINT_H + +#include "extensions/PxJoint.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + + class PxContactJoint; + + /** + \brief Create a distance Joint. + + \param[in] physics The physics SDK + \param[in] actor0 An actor to which the joint is attached. NULL may be used to attach the joint to a specific point in the world frame + \param[in] localFrame0 The position and orientation of the joint relative to actor0 + \param[in] actor1 An actor to which the joint is attached. NULL may be used to attach the joint to a specific point in the world frame + \param[in] localFrame1 The position and orientation of the joint relative to actor1 + + @see PxContactJoint + */ + PxContactJoint* PxContactJointCreate(PxPhysics& physics, PxRigidActor* actor0, const PxTransform& localFrame0, PxRigidActor* actor1, const PxTransform& localFrame1); + + /** + \brief a joint that maintains an upper or lower bound (or both) on the distance between two points on different objects + + @see PxContactJointCreate PxJoint + */ + + struct PxJacobianRow + { + PxVec3 linear0; + PxVec3 linear1; + PxVec3 angular0; + PxVec3 angular1; + + PxJacobianRow(){} + + PxJacobianRow(const PxVec3& lin0, const PxVec3& lin1, const PxVec3& ang0, const PxVec3& ang1) : + linear0(lin0), linear1(lin1), angular0(ang0), angular1(ang1) + { + + } + + void operator *= (const PxReal scale) + { + linear0 *= scale; + linear1 *= scale; + angular0 *= scale; + angular1 *= scale; + } + + PxJacobianRow operator * (const PxReal scale) const + { + return PxJacobianRow(linear0*scale, linear1*scale, angular0*scale, angular1*scale); + } + }; + + /** + \brief a joint that maintains an upper or lower bound (or both) on the distance between two points on different objects + + @see PxContactJointCreate PxJoint + */ + class PxContactJoint : public PxJoint + { + public: + + /** + \brief Set the current contact of the joint + */ + virtual void setContact(const PxVec3& contact) = 0; + + /** + \brief Set the current contact normal of the joint + */ + virtual void setContactNormal(const PxVec3& contactNormal) = 0; + + /** + \brief Set the current penetration of the joint + */ + virtual void setPenetration(const PxReal penetration) = 0; + + /** + \brief Return the current contact of the joint + */ + virtual PxVec3 getContact() const = 0; + + /** + \brief Return the current contact normal of the joint + */ + virtual PxVec3 getContactNormal() const = 0; + + /** + \brief Return the current penetration value of the joint + */ + virtual PxReal getPenetration() const = 0; + + virtual PxReal getResititution() const = 0; + virtual void setResititution(const PxReal resititution) = 0; + virtual PxReal getBounceThreshold() const = 0; + virtual void setBounceThreshold(const PxReal bounceThreshold) = 0; + + /** + \brief Returns string name of PxContactJoint, used for serialization + */ + virtual const char* getConcreteTypeName() const { return "PxContactJoint"; } + + virtual void computeJacobians(PxJacobianRow* jacobian) const = 0; + virtual PxU32 getNbJacobianRows() const = 0; + + protected: + //serialization + + /** + \brief Constructor + */ + PX_INLINE PxContactJoint(PxType concreteType, PxBaseFlags baseFlags) : PxJoint(concreteType, baseFlags) {} + + /** + \brief Deserialization constructor + */ + PX_INLINE PxContactJoint(PxBaseFlags baseFlags) : PxJoint(baseFlags) {} + + /** + \brief Returns whether a given type name matches with the type of this instance + */ + virtual bool isKindOf(const char* name) const { return !::strcmp("PxContactJoint", name) || PxJoint::isKindOf(name); } + + //~serialization + }; + +#if !PX_DOXYGEN +} +#endif + + +#endif diff --git a/sources/PhysX/PhysX/include/extensions/PxConvexMeshExt.h b/sources/PhysX/PhysX/include/extensions/PxConvexMeshExt.h new file mode 100644 index 00000000..5b33980d --- /dev/null +++ b/sources/PhysX/PhysX/include/extensions/PxConvexMeshExt.h @@ -0,0 +1,73 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_EXTENSIONS_CONVEX_MESH_H +#define PX_PHYSICS_EXTENSIONS_CONVEX_MESH_H +/** \addtogroup extensions + @{ +*/ + +#include "PxPhysXConfig.h" +#include "common/PxPhysXCommonConfig.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + + class PxConvexMeshGeometry; + + /** + \brief Computes closest polygon of the convex hull geometry for a given impact point + and impact direction. When doing sweeps against a scene, one might want to delay + the rather expensive computation of the hit face index for convexes until it is clear + the information is really needed and then use this method to get the corresponding + face index. + + \param[in] convexGeom The convex mesh geometry. + \param[in] geomPose Pose for the geometry object. + \param[in] impactPos Impact position. + \param[in] unitDir Normalized impact direction. + + \return Closest face index of the convex geometry. + + @see PxTransform PxConvexMeshGeometry + */ + PxU32 PxFindFaceIndex(const PxConvexMeshGeometry& convexGeom, + const PxTransform& geomPose, + const PxVec3& impactPos, + const PxVec3& unitDir); + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/extensions/PxD6Joint.h b/sources/PhysX/PhysX/include/extensions/PxD6Joint.h new file mode 100644 index 00000000..0b1cb6c3 --- /dev/null +++ b/sources/PhysX/PhysX/include/extensions/PxD6Joint.h @@ -0,0 +1,561 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_D6JOINT_H +#define PX_D6JOINT_H +/** \addtogroup extensions + @{ +*/ + +#include "extensions/PxJoint.h" +#include "extensions/PxJointLimit.h" +#include "foundation/PxFlags.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxD6Joint; + +/** +\brief Create a D6 joint. + + \param[in] physics The physics SDK + \param[in] actor0 An actor to which the joint is attached. NULL may be used to attach the joint to a specific point in the world frame + \param[in] localFrame0 The position and orientation of the joint relative to actor0 + \param[in] actor1 An actor to which the joint is attached. NULL may be used to attach the joint to a specific point in the world frame + \param[in] localFrame1 The position and orientation of the joint relative to actor1 + +@see PxD6Joint +*/ +PxD6Joint* PxD6JointCreate(PxPhysics& physics, PxRigidActor* actor0, const PxTransform& localFrame0, PxRigidActor* actor1, const PxTransform& localFrame1); + +/** +\brief Used to specify one of the degrees of freedom of a D6 joint. + +@see PxD6Joint +*/ +struct PxD6Axis +{ + enum Enum + { + eX = 0, //!< motion along the X axis + eY = 1, //!< motion along the Y axis + eZ = 2, //!< motion along the Z axis + eTWIST = 3, //!< motion around the X axis + eSWING1 = 4, //!< motion around the Y axis + eSWING2 = 5, //!< motion around the Z axis + eCOUNT = 6 + }; +}; + + +/** +\brief Used to specify the range of motions allowed for a degree of freedom in a D6 joint. + +@see PxD6Joint +*/ +struct PxD6Motion +{ + enum Enum + { + eLOCKED, //!< The DOF is locked, it does not allow relative motion. + eLIMITED, //!< The DOF is limited, it only allows motion within a specific range. + eFREE //!< The DOF is free and has its full range of motion. + }; +}; + + +/** +\brief Used to specify which axes of a D6 joint are driven. + +Each drive is an implicit force-limited damped spring: + +force = spring * (target position - position) + damping * (targetVelocity - velocity) + +Alternatively, the spring may be configured to generate a specified acceleration instead of a force. + +A linear axis is affected by drive only if the corresponding drive flag is set. There are two possible models +for angular drive: swing/twist, which may be used to drive one or more angular degrees of freedom, or slerp, +which may only be used to drive all three angular degrees simultaneously. + +@see PxD6Joint +*/ +struct PxD6Drive +{ + enum Enum + { + eX = 0, //!< drive along the X-axis + eY = 1, //!< drive along the Y-axis + eZ = 2, //!< drive along the Z-axis + eSWING = 3, //!< drive of displacement from the X-axis + eTWIST = 4, //!< drive of the displacement around the X-axis + eSLERP = 5, //!< drive of all three angular degrees along a SLERP-path + eCOUNT = 6 + }; +}; + +/** +\brief flags for configuring the drive model of a PxD6Joint + +@see PxD6JointDrive PxD6Joint +*/ +struct PxD6JointDriveFlag +{ + enum Enum + { + eACCELERATION = 1 //!< drive spring is for the acceleration at the joint (rather than the force) + }; +}; +typedef PxFlags PxD6JointDriveFlags; +PX_FLAGS_OPERATORS(PxD6JointDriveFlag::Enum, PxU32) + +/** +\brief parameters for configuring the drive model of a PxD6Joint + +@see PxD6Joint +*/ +class PxD6JointDrive : public PxSpring +{ +//= ATTENTION! ===================================================================================== +// Changing the data layout of this class breaks the binary serialization format. See comments for +// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData +// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION +// accordingly. +//================================================================================================== + +public: + PxReal forceLimit; //!< the force limit of the drive - may be an impulse or a force depending on PxConstraintFlag::eDRIVE_LIMITS_ARE_FORCES + PxD6JointDriveFlags flags; //!< the joint drive flags + + /** + \brief default constructor for PxD6JointDrive. + */ + PxD6JointDrive(): PxSpring(0,0), forceLimit(PX_MAX_F32), flags(0) {} + + /** + \brief constructor a PxD6JointDrive. + + \param[in] driveStiffness The stiffness of the drive spring. + \param[in] driveDamping The damping of the drive spring + \param[in] driveForceLimit The maximum impulse or force that can be exerted by the drive + \param[in] isAcceleration Whether the drive is an acceleration drive or a force drive + */ + PxD6JointDrive(PxReal driveStiffness, PxReal driveDamping, PxReal driveForceLimit, bool isAcceleration = false) + : PxSpring(driveStiffness, driveDamping) + , forceLimit(driveForceLimit) + , flags(isAcceleration?PxU32(PxD6JointDriveFlag::eACCELERATION) : 0) + {} + + /** + \brief returns true if the drive is valid + */ + bool isValid() const + { + return PxIsFinite(stiffness) && stiffness>=0 && + PxIsFinite(damping) && damping >=0 && + PxIsFinite(forceLimit) && forceLimit >=0; + } +}; + + +/** + \brief A D6 joint is a general constraint between two actors. + + It allows the application to individually define the linear and rotational degrees of freedom, + and also to configure a variety of limits and driven degrees of freedom. + + By default all degrees of freedom are locked. So to create a prismatic joint with free motion + along the x-axis: + + \code + ... + joint->setMotion(PxD6Axis::eX, PxD6JointMotion::eFREE); + ... + \endcode + + Or a Revolute joint with motion free allowed around the x-axis: + + \code + ... + joint->setMotion(PxD6Axis::eTWIST, PxD6JointMotion::eFREE); + ... + \endcode + + Degrees of freedom may also be set to limited instead of locked. + + There are two different kinds of linear limits available. The first kind is a single limit value + for all linear degrees of freedom, which may act as a linear, circular, or spherical limit depending + on which degrees of freedom are limited. This is similar to a distance limit. Then, the second kind + supports a pair of limit values for each linear axis, which can be used to implement a traditional + prismatic joint for example. + + If the twist degree of freedom is limited, is supports upper and lower limits. The two swing degrees + of freedom are limited with a cone limit. +@see PxD6JointCreate() PxJoint +*/ +class PxD6Joint : public PxJoint +{ +public: + + /** + \brief Set the motion type around the specified axis. + + Each axis may independently specify that the degree of freedom is locked (blocking relative movement + along or around this axis), limited by the corresponding limit, or free. + + \param[in] axis the axis around which motion is specified + \param[in] type the motion type around the specified axis + + Default: all degrees of freedom are locked + + @see getMotion() PxD6Axis PxD6Motion + */ + virtual void setMotion(PxD6Axis::Enum axis, PxD6Motion::Enum type) = 0; + + /** + \brief Get the motion type around the specified axis. + + @see setMotion() PxD6Axis PxD6Motion + + \param[in] axis the degree of freedom around which the motion type is specified + \return the motion type around the specified axis + */ + virtual PxD6Motion::Enum getMotion(PxD6Axis::Enum axis) const = 0; + + /** + \brief get the twist angle of the joint, in the range (-2*Pi, 2*Pi] + */ + virtual PxReal getTwistAngle() const = 0; + + /** + \brief get the twist angle of the joint + + \deprecated Use getTwistAngle instead. Deprecated since PhysX version 4.0 + */ + PX_DEPRECATED PX_FORCE_INLINE PxReal getTwist() const { return getTwistAngle(); } + + /** + \brief get the swing angle of the joint from the Y axis + */ + virtual PxReal getSwingYAngle() const = 0; + + /** + \brief get the swing angle of the joint from the Z axis + */ + virtual PxReal getSwingZAngle() const = 0; + + /** + \brief Set the distance limit for the joint. + + A single limit constraints all linear limited degrees of freedom, forming a linear, circular + or spherical constraint on motion depending on the number of limited degrees. This is similar + to a distance limit. + + \param[in] limit the distance limit structure + + @see getDistanceLimit() PxJointLinearLimit + */ + virtual void setDistanceLimit(const PxJointLinearLimit& limit) = 0; + + /** + \brief Get the distance limit for the joint. + + \return the distance limit structure + + @see setDistanceLimit() PxJointLinearLimit + */ + virtual PxJointLinearLimit getDistanceLimit() const = 0; + + /** + \deprecated Use setDistanceLimit instead. Deprecated since PhysX version 4.0 + */ + PX_DEPRECATED PX_FORCE_INLINE void setLinearLimit(const PxJointLinearLimit& limit) { setDistanceLimit(limit); } + + /** + \deprecated Use getDistanceLimit instead. Deprecated since PhysX version 4.0 + */ + PX_DEPRECATED PX_FORCE_INLINE PxJointLinearLimit getLinearLimit() const { return getDistanceLimit(); } + + /** + \brief Set the linear limit for a given linear axis. + + This function extends the previous setDistanceLimit call with the following features: + - there can be a different limit for each linear axis + - each limit is defined by two values, i.e. it can now be asymmetric + + This can be used to create prismatic joints similar to PxPrismaticJoint, or point-in-quad joints, + or point-in-box joints. + + \param[in] axis The limited linear axis (must be PxD6Axis::eX, PxD6Axis::eY or PxD6Axis::eZ) + \param[in] limit The linear limit pair structure + + @see getLinearLimit() + */ + virtual void setLinearLimit(PxD6Axis::Enum axis, const PxJointLinearLimitPair& limit) = 0; + + /** + \brief Get the linear limit for a given linear axis. + + \param[in] axis The limited linear axis (must be PxD6Axis::eX, PxD6Axis::eY or PxD6Axis::eZ) + + \return the linear limit pair structure from desired axis + + @see setLinearLimit() PxJointLinearLimit + */ + virtual PxJointLinearLimitPair getLinearLimit(PxD6Axis::Enum axis) const = 0; + + /** + \brief Set the twist limit for the joint. + + The twist limit controls the range of motion around the twist axis. + + The limit angle range is (-2*Pi, 2*Pi). + + \param[in] limit the twist limit structure + + @see getTwistLimit() PxJointAngularLimitPair + */ + virtual void setTwistLimit(const PxJointAngularLimitPair& limit) = 0; + + /** + \brief Get the twist limit for the joint. + + \return the twist limit structure + + @see setTwistLimit() PxJointAngularLimitPair + */ + virtual PxJointAngularLimitPair getTwistLimit() const = 0; + + /** + \brief Set the swing cone limit for the joint. + + The cone limit is used if either or both swing axes are limited. The extents are + symmetrical and measured in the frame of the parent. If only one swing degree of freedom + is limited, the corresponding value from the cone limit defines the limit range. + + \param[in] limit the cone limit structure + + @see getLimitCone() PxJointLimitCone + */ + virtual void setSwingLimit(const PxJointLimitCone& limit) = 0; + + /** + \brief Get the cone limit for the joint. + + \return the swing limit structure + + @see setLimitCone() PxJointLimitCone + */ + virtual PxJointLimitCone getSwingLimit() const = 0; + + /** + \brief Set a pyramidal swing limit for the joint. + + The pyramid limits will only be used in the following cases: + - both swing Y and Z are limited. The limit shape is then a pyramid. + - Y is limited and Z is locked, or vice versa. The limit shape is an asymmetric angular section, similar to + what is supported for the twist axis. + The remaining cases (Y limited and Z is free, or vice versa) are not supported. + + \param[in] limit the cone limit structure + + @see getLimitCone() PxJointLimitPyramid + */ + virtual void setPyramidSwingLimit(const PxJointLimitPyramid& limit) = 0; + + /** + \brief Get the pyramidal swing limit for the joint. + + \return the swing limit structure + + @see setLimitCone() PxJointLimitPyramid + */ + virtual PxJointLimitPyramid getPyramidSwingLimit() const = 0; + + /** + \brief Set the drive parameters for the specified drive type. + + \param[in] index the type of drive being specified + \param[in] drive the drive parameters + + @see getDrive() PxD6JointDrive + + Default The default drive spring and damping values are zero, the force limit is zero, and no flags are set. + */ + virtual void setDrive(PxD6Drive::Enum index, const PxD6JointDrive& drive) = 0; + + /** + \brief Get the drive parameters for the specified drive type. + + \param[in] index the specified drive type + + @see setDrive() PxD6JointDrive + */ + virtual PxD6JointDrive getDrive(PxD6Drive::Enum index) const = 0; + + /** + \brief Set the drive goal pose + + The goal is relative to the constraint frame of actor[0] + + Default the identity transform + + \param[in] pose The goal drive pose if positional drive is in use. + \param[in] autowake Whether to wake the joint rigids up if it is asleep. + + @see setDrivePosition() + */ + virtual void setDrivePosition(const PxTransform& pose, bool autowake = true) = 0; + + /** + \brief Get the drive goal pose. + + @see getDrivePosition() + */ + virtual PxTransform getDrivePosition() const = 0; + + /** + \brief Set the target goal velocity for drive. + + The velocity is measured in the constraint frame of actor[0] + + \param[in] linear The goal velocity for linear drive + \param[in] angular The goal velocity for angular drive + \param[in] autowake Whether to wake the joint rigids up if it is asleep. + + @see getDriveVelocity() + */ + virtual void setDriveVelocity(const PxVec3& linear, const PxVec3& angular, bool autowake = true) = 0; + + /** + \brief Get the target goal velocity for joint drive. + + \param[in] linear The goal velocity for linear drive + \param[in] angular The goal velocity for angular drive + + @see setDriveVelocity() + */ + virtual void getDriveVelocity(PxVec3& linear, PxVec3& angular) const = 0; + + /** + \brief Set the linear tolerance threshold for projection. Projection is enabled if PxConstraintFlag::ePROJECTION + is set for the joint. + + If the joint separates by more than this distance along its locked degrees of freedom, the solver + will move the bodies to close the distance. + + Setting a very small tolerance may result in simulation jitter or other artifacts. + + Sometimes it is not possible to project (for example when the joints form a cycle). + + Range: [0, PX_MAX_F32)
+ Default: 1e10f + + \param[in] tolerance the linear tolerance threshold + + @see getProjectionLinearTolerance() PxJoint::setConstraintFlags() PxConstraintFlag::ePROJECTION + */ + virtual void setProjectionLinearTolerance(PxReal tolerance) = 0; + + /** + \brief Get the linear tolerance threshold for projection. + + \return the linear tolerance threshold + + @see setProjectionLinearTolerance() + */ + virtual PxReal getProjectionLinearTolerance() const = 0; + + /** + \brief Set the angular tolerance threshold for projection. Projection is enabled if + PxConstraintFlag::ePROJECTION is set for the joint. + + If the joint deviates by more than this angle around its locked angular degrees of freedom, + the solver will move the bodies to close the angle. + + Setting a very small tolerance may result in simulation jitter or other artifacts. + + Sometimes it is not possible to project (for example when the joints form a cycle). + + Range: [0,Pi]
+ Default: Pi + + \param[in] tolerance the angular tolerance threshold in radians + + \note + Angular projection is implemented only for the case of two or three locked angular degrees of freedom. + + @see getProjectionAngularTolerance() PxJoint::setConstraintFlag() PxConstraintFlag::ePROJECTION + */ + virtual void setProjectionAngularTolerance(PxReal tolerance) = 0; + + /** + \brief Get the angular tolerance threshold for projection. + + \return tolerance the angular tolerance threshold in radians + + @see setProjectionAngularTolerance() + */ + virtual PxReal getProjectionAngularTolerance() const = 0; + + /** + \brief Returns string name of PxD6Joint, used for serialization + */ + virtual const char* getConcreteTypeName() const { return "PxD6Joint"; } + +protected: + + //serialization + + /** + \brief Constructor + */ + PX_INLINE PxD6Joint(PxType concreteType, PxBaseFlags baseFlags) : PxJoint(concreteType, baseFlags) {} + + /** + \brief Deserialization constructor + */ + PX_INLINE PxD6Joint(PxBaseFlags baseFlags) : PxJoint(baseFlags) {} + + /** + \brief Returns whether a given type name matches with the type of this instance + */ + virtual bool isKindOf(const char* name) const { return !::strcmp("PxD6Joint", name) || PxJoint::isKindOf(name); } + + //~serialization +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/extensions/PxD6JointCreate.h b/sources/PhysX/PhysX/include/extensions/PxD6JointCreate.h new file mode 100644 index 00000000..8459dce5 --- /dev/null +++ b/sources/PhysX/PhysX/include/extensions/PxD6JointCreate.h @@ -0,0 +1,255 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_D6JOINT_CREATE_H +#define PX_D6JOINT_CREATE_H + +#include "common/PxPhysXCommonConfig.h" + +/** \addtogroup extensions + @{ +*/ + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxPhysics; +class PxRigidActor; +class PxJoint; + +/** + \brief Helper function to create a fixed joint, using either a PxD6Joint or PxFixedJoint. + + For fixed joints it is important that the joint frames have the same orientation. This helper function uses an identity rotation for both. + It is also important that the joint frames have an equivalent position in world space. The function does not check this, so it is up to users + to ensure that this is the case. + + \param[in] physics The physics SDK + \param[in] actor0 An actor to which the joint is attached. NULL may be used to attach the joint to a specific point in the world frame + \param[in] localPos0 The position of the joint relative to actor0 + \param[in] actor1 An actor to which the joint is attached. NULL may be used to attach the joint to a specific point in the world frame + \param[in] localPos1 The position of the joint relative to actor1 + \param[in] useD6 True to use a PxD6Joint, false to use a PxFixedJoint; + + \return The created joint. + + @see PxD6Joint PxFixedJoint +*/ +PxJoint* PxD6JointCreate_Fixed(PxPhysics& physics, PxRigidActor* actor0, const PxVec3& localPos0, PxRigidActor* actor1, const PxVec3& localPos1, bool useD6); + +/** + \brief Helper function to create a distance joint, using either a PxD6Joint or PxDistanceJoint. + + This helper function only supports a maximum distance constraint, because PxD6Joint does not support a minimum distance constraint (contrary + to PxDistanceJoint). + + The distance is computed between the joint frames' world-space positions. The joint frames' orientations are irrelevant here so the function + sets them to identity. + + \param[in] physics The physics SDK + \param[in] actor0 An actor to which the joint is attached. NULL may be used to attach the joint to a specific point in the world frame + \param[in] localPos0 The position of the joint relative to actor0 + \param[in] actor1 An actor to which the joint is attached. NULL may be used to attach the joint to a specific point in the world frame + \param[in] localPos1 The position of the joint relative to actor1 + \param[in] maxDist The maximum allowed distance + \param[in] useD6 True to use a PxD6Joint, false to use a PxDistanceJoint; + + \return The created joint. + + @see PxD6Joint PxDistanceJoint +*/ +PxJoint* PxD6JointCreate_Distance(PxPhysics& physics, PxRigidActor* actor0, const PxVec3& localPos0, PxRigidActor* actor1, const PxVec3& localPos1, float maxDist, bool useD6); + +/** + \brief Helper function to create a prismatic joint, using either a PxD6Joint or PxPrismaticJoint. + + This function enforces that the joint frames have the same orientation, which is a local frame whose X is the desired translation axis. + This orientation is computed by the function, so users only have to define the desired translation axis (typically 1;0;0 or 0;1;0 or 0;0;1). + + The translation can be limited. Limits are enforced if minLimitmaxLimit the + limits are not enforced and the axis is free. The limit values are computed relative to the position of actor0's joint frame. + + The function creates hard limits, and uses PhysX's default contact distance parameter. + + \param[in] physics The physics SDK + \param[in] actor0 An actor to which the joint is attached. NULL may be used to attach the joint to a specific point in the world frame + \param[in] localPos0 The position of the joint relative to actor0 + \param[in] actor1 An actor to which the joint is attached. NULL may be used to attach the joint to a specific point in the world frame + \param[in] localPos1 The position of the joint relative to actor1 + \param[in] axis The axis along which objects are allowed to move, expressed in the actors' local space + \param[in] minLimit The minimum allowed position along the axis + \param[in] maxLimit The maximum allowed position along the axis + \param[in] useD6 True to use a PxD6Joint, false to use a PxPrismaticJoint; + + \return The created joint. + + @see PxD6Joint PxPrismaticJoint +*/ +PxJoint* PxD6JointCreate_Prismatic(PxPhysics& physics, PxRigidActor* actor0, const PxVec3& localPos0, PxRigidActor* actor1, const PxVec3& localPos1, const PxVec3& axis, float minLimit, float maxLimit, bool useD6); + +/** + \brief Helper function to create a revolute joint, using either a PxD6Joint or PxRevoluteJoint. + + This function enforces that the joint frames have the same orientation, which is a local frame whose X is the desired rotation axis. + This orientation is computed by the function, so users only have to define the desired rotation axis (typically 1;0;0 or 0;1;0 or 0;0;1). + + The rotation can be limited. Limits are enforced if minLimitmaxLimit the + limits are not enforced and the axis is free. The limit values are computed relative to the rotation of actor0's joint frame. + + The function creates hard limits, and uses PhysX's default contact distance parameter. + + Limits are expressed in radians. Allowed range is ]-2*PI;+2*PI[ + + \param[in] physics The physics SDK + \param[in] actor0 An actor to which the joint is attached. NULL may be used to attach the joint to a specific point in the world frame + \param[in] localPos0 The position of the joint relative to actor0 + \param[in] actor1 An actor to which the joint is attached. NULL may be used to attach the joint to a specific point in the world frame + \param[in] localPos1 The position of the joint relative to actor1 + \param[in] axis The axis around which objects are allowed to move, expressed in the actors' local space + \param[in] minLimit The minimum allowed rotation along the axis + \param[in] maxLimit The maximum allowed rotation along the axis + \param[in] useD6 True to use a PxD6Joint, false to use a PxRevoluteJoint; + + \return The created joint. + + @see PxD6Joint PxRevoluteJoint +*/ +PxJoint* PxD6JointCreate_Revolute(PxPhysics& physics, PxRigidActor* actor0, const PxVec3& localPos0, PxRigidActor* actor1, const PxVec3& localPos1, const PxVec3& axis, float minLimit, float maxLimit, bool useD6); + +/** + \brief Helper function to create a spherical joint, using either a PxD6Joint or PxSphericalJoint. + + This function supports a cone limit shape, defined by a cone axis and two angular limit values. + + This function enforces that the joint frames have the same orientation, which is a local frame whose X is the desired cone axis. + This orientation is computed by the function, so users only have to define the desired cone axis (typically 1;0;0 or 0;1;0 or 0;0;1). + + The rotations can be limited. Limits are enforced if limit1>0 and limit2>0. Otherwise the motion is free. The limit values define an ellipse, + which is the cross-section of the cone limit shape. + + The function creates hard limits, and uses PhysX's default contact distance parameter. + + Limits are expressed in radians. Allowed range is ]0;PI[. Limits are symmetric around the cone axis. + + The cone axis is equivalent to the twist axis for the D6 joint. The twist motion is not limited. + + \param[in] physics The physics SDK + \param[in] actor0 An actor to which the joint is attached. NULL may be used to attach the joint to a specific point in the world frame + \param[in] localPos0 The position of the joint relative to actor0 + \param[in] actor1 An actor to which the joint is attached. NULL may be used to attach the joint to a specific point in the world frame + \param[in] localPos1 The position of the joint relative to actor1 + \param[in] axis The cone axis, expressed in the actors' local space + \param[in] limit1 Max angular limit for the ellipse along the joint frame's second axis (first axis = cone axis) + \param[in] limit2 Max angular limit for the ellipse along the joint frame's third axis (first axis = cone axis) + \param[in] useD6 True to use a PxD6Joint, false to use a PxSphericalJoint; + + \return The created joint. + + @see PxD6Joint PxSphericalJoint +*/ +PxJoint* PxD6JointCreate_Spherical(PxPhysics& physics, PxRigidActor* actor0, const PxVec3& localPos0, PxRigidActor* actor1, const PxVec3& localPos1, const PxVec3& axis, float limit1, float limit2, bool useD6); + +/** + \brief Helper function to create a spherical joint, using either a PxD6Joint or PxSphericalJoint. + + This function supports a cone limit shape, defined by two pairs of angular limit values. This can be used to create an asymmetric cone. If the + angular limit values are symmetric (i.e. minLimit1=-maxLimit1 and minLimit2=-maxLimit2) then the cone axis is the X axis in actor0's space. + If the limits are not symmetric, the function rotates the cone axis accordingly so that limits remain symmetric for PhysX. If this happens, + the initial joint frames will be different for both actors. By default minLimit1/maxLimit1 are limits around the joint's Y axis, and + minLimit2/maxLimit2 are limits around the joint's Z axis. + + The function creates hard limits, and uses PhysX's default contact distance parameter. + + Limits are expressed in radians. Allowed range is ]-PI;PI[. + + The cone axis is equivalent to the twist axis for the D6 joint. The twist motion is not limited. + + The returned apiroty and apirotz values can later be added to retrieved Y and Z swing angle values (from the joint), to remap + angle values to the given input range. + + \param[out] apiroty Amount of rotation around Y used to setup actor0's joint frame + \param[out] apirotz Amount of rotation around Z used to setup actor0's joint frame + \param[in] physics The physics SDK + \param[in] actor0 An actor to which the joint is attached. NULL may be used to attach the joint to a specific point in the world frame + \param[in] localPos0 The position of the joint relative to actor0 + \param[in] actor1 An actor to which the joint is attached. NULL may be used to attach the joint to a specific point in the world frame + \param[in] localPos1 The position of the joint relative to actor1 + \param[in] minLimit1 Min angular limit along the joint frame's second axis (first axis = cone axis) + \param[in] maxLimit1 Max angular limit along the joint frame's second axis (first axis = cone axis) + \param[in] minLimit2 Min angular limit along the joint frame's third axis (first axis = cone axis) + \param[in] maxLimit2 Max angular limit along the joint frame's third axis (first axis = cone axis) + \param[in] useD6 True to use a PxD6Joint, false to use a PxSphericalJoint; + + \return The created joint. + + @see PxD6Joint PxSphericalJoint +*/ +PxJoint* PxD6JointCreate_GenericCone(float& apiroty, float& apirotz, PxPhysics& physics, PxRigidActor* actor0, const PxVec3& localPos0, PxRigidActor* actor1, const PxVec3& localPos1, float minLimit1, float maxLimit1, float minLimit2, float maxLimit2, bool useD6); + + +/** + \brief Helper function to create a D6 joint with pyramidal swing limits. + + This function supports a pyramid limit shape, defined by two pairs of angular limit values. This can be used to create an asymmetric pyramid. If the + angular limit values are symmetric (i.e. minLimit1=-maxLimit1 and minLimit2=-maxLimit2) then the pyramid axis is the X axis in actor0's space. + By default minLimit1/maxLimit1 are limits around the joint's Y axis, and minLimit2/maxLimit2 are limits around the joint's Z axis. + + The function creates hard limits, and uses PhysX's default contact distance parameter. + + Limits are expressed in radians. Allowed range is ]-PI;PI[. + + The pyramid axis is equivalent to the twist axis for the D6 joint. The twist motion is not limited. + + \param[in] physics The physics SDK + \param[in] actor0 An actor to which the joint is attached. NULL may be used to attach the joint to a specific point in the world frame + \param[in] localPos0 The position of the joint relative to actor0 + \param[in] actor1 An actor to which the joint is attached. NULL may be used to attach the joint to a specific point in the world frame + \param[in] localPos1 The position of the joint relative to actor1 + \param[in] axis The pyramid axis, expressed in the actors' local space + \param[in] minLimit1 Min angular limit along the joint frame's second axis (first axis = pyramid axis) + \param[in] maxLimit1 Max angular limit along the joint frame's second axis (first axis = pyramid axis) + \param[in] minLimit2 Min angular limit along the joint frame's third axis (first axis = pyramid axis) + \param[in] maxLimit2 Max angular limit along the joint frame's third axis (first axis = pyramid axis) + + \return The created joint. + + @see PxD6Joint +*/ +PxJoint* PxD6JointCreate_Pyramid(PxPhysics& physics, PxRigidActor* actor0, const PxVec3& localPos0, PxRigidActor* actor1, const PxVec3& localPos1, const PxVec3& axis, + float minLimit1, float maxLimit1, float minLimit2, float maxLimit2); + + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/extensions/PxDefaultAllocator.h b/sources/PhysX/PhysX/include/extensions/PxDefaultAllocator.h new file mode 100644 index 00000000..8c24172d --- /dev/null +++ b/sources/PhysX/PhysX/include/extensions/PxDefaultAllocator.h @@ -0,0 +1,110 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_DEFAULT_ALLOCATOR_H +#define PX_DEFAULT_ALLOCATOR_H +/** \addtogroup extensions + @{ +*/ + +#include "foundation/PxAllocatorCallback.h" +#include "foundation/PxAssert.h" +#include "common/PxPhysXCommonConfig.h" + +#include + +#if PX_WINDOWS_FAMILY || PX_LINUX_FAMILY || PX_SWITCH +#include +#endif + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +#if PX_WINDOWS_FAMILY +// on win32 we only have 8-byte alignment guaranteed, but the CRT provides special aligned allocation fns +PX_FORCE_INLINE void* platformAlignedAlloc(size_t size) +{ + return _aligned_malloc(size, 16); +} + +PX_FORCE_INLINE void platformAlignedFree(void* ptr) +{ + _aligned_free(ptr); +} +#elif PX_LINUX_FAMILY || PX_SWITCH +PX_FORCE_INLINE void* platformAlignedAlloc(size_t size) +{ + return ::memalign(16, size); +} + +PX_FORCE_INLINE void platformAlignedFree(void* ptr) +{ + ::free(ptr); +} +#else +// on all other platforms we get 16-byte alignment by default +PX_FORCE_INLINE void* platformAlignedAlloc(size_t size) +{ + return ::malloc(size); +} + +PX_FORCE_INLINE void platformAlignedFree(void* ptr) +{ + ::free(ptr); +} +#endif + +/** +\brief default implementation of the allocator interface required by the SDK +*/ +class PxDefaultAllocator : public PxAllocatorCallback +{ +public: + void* allocate(size_t size, const char*, const char*, int) + { + void* ptr = platformAlignedAlloc(size); + PX_ASSERT((reinterpret_cast(ptr) & 15)==0); + return ptr; + } + + void deallocate(void* ptr) + { + platformAlignedFree(ptr); + } +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/extensions/PxDefaultCpuDispatcher.h b/sources/PhysX/PhysX/include/extensions/PxDefaultCpuDispatcher.h new file mode 100644 index 00000000..8ad081cc --- /dev/null +++ b/sources/PhysX/PhysX/include/extensions/PxDefaultCpuDispatcher.h @@ -0,0 +1,98 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_EXTENSIONS_DEFAULT_CPU_DISPATCHER_H +#define PX_PHYSICS_EXTENSIONS_DEFAULT_CPU_DISPATCHER_H +/** \addtogroup extensions + @{ +*/ + +#include "common/PxPhysXCommonConfig.h" +#include "task/PxCpuDispatcher.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief A default implementation for a CPU task dispatcher. + +@see PxDefaultCpuDispatcherCreate() PxCpuDispatcher +*/ +class PxDefaultCpuDispatcher: public PxCpuDispatcher +{ +public: + /** + \brief Deletes the dispatcher. + + Do not keep a reference to the deleted instance. + + @see PxDefaultCpuDispatcherCreate() + */ + virtual void release() = 0; + + /** + \brief Enables profiling at task level. + + \note By default enabled only in profiling builds. + + \param[in] runProfiled True if tasks should be profiled. + */ + virtual void setRunProfiled(bool runProfiled) = 0; + + /** + \brief Checks if profiling is enabled at task level. + + \return True if tasks should be profiled. + */ + virtual bool getRunProfiled() const = 0; +}; + + +/** +\brief Create default dispatcher, extensions SDK needs to be initialized first. + +\param[in] numThreads Number of worker threads the dispatcher should use. +\param[in] affinityMasks Array with affinity mask for each thread. If not defined, default masks will be used. + +\note numThreads may be zero in which case no worker thread are initialized and +simulation tasks will be executed on the thread that calls PxScene::simulate() + +@see PxDefaultCpuDispatcher +*/ +PxDefaultCpuDispatcher* PxDefaultCpuDispatcherCreate(PxU32 numThreads, PxU32* affinityMasks = NULL); + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/extensions/PxDefaultErrorCallback.h b/sources/PhysX/PhysX/include/extensions/PxDefaultErrorCallback.h new file mode 100644 index 00000000..cec365e9 --- /dev/null +++ b/sources/PhysX/PhysX/include/extensions/PxDefaultErrorCallback.h @@ -0,0 +1,62 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_PHYSICS_EXTENSIONS_DEFAULT_ERROR_CALLBACK_H +#define PX_PHYSICS_EXTENSIONS_DEFAULT_ERROR_CALLBACK_H + +#include "foundation/PxErrorCallback.h" +#include "PxPhysXConfig.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + + /** + \brief default implementation of the error callback + + This class is provided in order to enable the SDK to be started with the minimum of user code. Typically an application + will use its own error callback, and log the error to file or otherwise make it visible. Warnings and error messages from + the SDK are usually indicative that changes are required in order for PhysX to function correctly, and should not be ignored. + */ + + class PxDefaultErrorCallback : public PxErrorCallback + { + public: + PxDefaultErrorCallback(); + ~PxDefaultErrorCallback(); + + virtual void reportError(PxErrorCode::Enum code, const char* message, const char* file, int line); + }; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +#endif diff --git a/sources/PhysX/PhysX/include/extensions/PxDefaultSimulationFilterShader.h b/sources/PhysX/PhysX/include/extensions/PxDefaultSimulationFilterShader.h new file mode 100644 index 00000000..70d88af5 --- /dev/null +++ b/sources/PhysX/PhysX/include/extensions/PxDefaultSimulationFilterShader.h @@ -0,0 +1,263 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_EXTENSIONS_DEFAULTSIMULATIONFILTERSHADER_H +#define PX_PHYSICS_EXTENSIONS_DEFAULTSIMULATIONFILTERSHADER_H +/** \addtogroup extensions + @{ +*/ + +#include "PxPhysXConfig.h" + +#include "PxFiltering.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxActor; + +/** +\brief 64-bit mask used for collision filtering. + +The collision filtering equation for 2 objects o0 and o1 is: + +
 (G0 op0 K0) op2 (G1 op1 K1) == b 
+ +with + +
    +
  • G0 = PxGroupsMask for object o0. See PxSetGroupsMask
  • +
  • G1 = PxGroupsMask for object o1. See PxSetGroupsMask
  • +
  • K0 = filtering constant 0. See PxSetFilterConstants
  • +
  • K1 = filtering constant 1. See PxSetFilterConstants
  • +
  • b = filtering boolean. See PxSetFilterBool
  • +
  • op0, op1, op2 = filtering operations. See PxSetFilterOps
  • +
+ +If the filtering equation is true, collision detection is enabled. + +@see PxSetFilterOps() +*/ +class PxGroupsMask +{ +public: + PX_INLINE PxGroupsMask():bits0(0),bits1(0),bits2(0),bits3(0) {} + PX_INLINE ~PxGroupsMask() {} + + PxU16 bits0, bits1, bits2, bits3; +}; + +/** +\brief Collision filtering operations. + +@see PxGroupsMask +*/ +struct PxFilterOp +{ + enum Enum + { + PX_FILTEROP_AND, + PX_FILTEROP_OR, + PX_FILTEROP_XOR, + PX_FILTEROP_NAND, + PX_FILTEROP_NOR, + PX_FILTEROP_NXOR, + PX_FILTEROP_SWAP_AND + }; +}; + +/** +\brief Implementation of a simple filter shader that emulates PhysX 2.8.x filtering + +This shader provides the following logic: +\li If one of the two filter objects is a trigger, the pair is acccepted and #PxPairFlag::eTRIGGER_DEFAULT will be used for trigger reports +\li Else, if the filter mask logic (see further below) discards the pair it will be suppressed (#PxFilterFlag::eSUPPRESS) +\li Else, the pair gets accepted and collision response gets enabled (#PxPairFlag::eCONTACT_DEFAULT) + +Filter mask logic: +Given the two #PxFilterData structures fd0 and fd1 of two collision objects, the pair passes the filter if the following +conditions are met: + + 1) Collision groups of the pair are enabled + 2) Collision filtering equation is satisfied + +@see PxSimulationFilterShader +*/ + +PxFilterFlags PxDefaultSimulationFilterShader( + PxFilterObjectAttributes attributes0, + PxFilterData filterData0, + PxFilterObjectAttributes attributes1, + PxFilterData filterData1, + PxPairFlags& pairFlags, + const void* constantBlock, + PxU32 constantBlockSize); + +/** + \brief Determines if collision detection is performed between a pair of groups + + \note Collision group is an integer between 0 and 31. + + \param[in] group1 First Group + \param[in] group2 Second Group + + \return True if the groups could collide + + @see PxSetGroupCollisionFlag +*/ +bool PxGetGroupCollisionFlag(const PxU16 group1, const PxU16 group2); + +/** + \brief Specifies if collision should be performed by a pair of groups + + \note Collision group is an integer between 0 and 31. + + \param[in] group1 First Group + \param[in] group2 Second Group + \param[in] enable True to enable collision between the groups + + @see PxGetGroupCollisionFlag +*/ +void PxSetGroupCollisionFlag(const PxU16 group1, const PxU16 group2, const bool enable); + +/** + \brief Retrieves the value set with PxSetGroup() + + \note Collision group is an integer between 0 and 31. + + \param[in] actor The actor + + \return The collision group this actor belongs to + + @see PxSetGroup +*/ +PxU16 PxGetGroup(const PxActor& actor); + +/** + \brief Sets which collision group this actor is part of + + \note Collision group is an integer between 0 and 31. + + \param[in] actor The actor + \param[in] collisionGroup Collision group this actor belongs to + + @see PxGetGroup +*/ +void PxSetGroup(PxActor& actor, const PxU16 collisionGroup); + +/** +\brief Retrieves filtering operation. See comments for PxGroupsMask + +\param[out] op0 First filter operator. +\param[out] op1 Second filter operator. +\param[out] op2 Third filter operator. + +@see PxSetFilterOps PxSetFilterBool PxSetFilterConstants +*/ +void PxGetFilterOps(PxFilterOp::Enum& op0, PxFilterOp::Enum& op1, PxFilterOp::Enum& op2); + +/** +\brief Setups filtering operations. See comments for PxGroupsMask + +\param[in] op0 Filter op 0. +\param[in] op1 Filter op 1. +\param[in] op2 Filter op 2. + +@see PxSetFilterBool PxSetFilterConstants +*/ +void PxSetFilterOps(const PxFilterOp::Enum& op0, const PxFilterOp::Enum& op1, const PxFilterOp::Enum& op2); + +/** +\brief Retrieves filtering's boolean value. See comments for PxGroupsMask + +\return flag Boolean value for filter. + +@see PxSetFilterBool PxSetFilterConstants +*/ +bool PxGetFilterBool(); + +/** +\brief Setups filtering's boolean value. See comments for PxGroupsMask + +\param[in] enable Boolean value for filter. + +@see PxSetFilterOps PxSsetFilterConstants +*/ +void PxSetFilterBool(const bool enable); + +/** +\brief Gets filtering constant K0 and K1. See comments for PxGroupsMask + +\param[out] c0 the filtering constants, as a mask. See #PxGroupsMask. +\param[out] c1 the filtering constants, as a mask. See #PxGroupsMask. + +@see PxSetFilterOps PxSetFilterBool PxSetFilterConstants +*/ +void PxGetFilterConstants(PxGroupsMask& c0, PxGroupsMask& c1); + +/** +\brief Setups filtering's K0 and K1 value. See comments for PxGroupsMask + +\param[in] c0 The new group mask. See #PxGroupsMask. +\param[in] c1 The new group mask. See #PxGroupsMask. + +@see PxSetFilterOps PxSetFilterBool PxGetFilterConstants +*/ +void PxSetFilterConstants(const PxGroupsMask& c0, const PxGroupsMask& c1); + +/** +\brief Gets 64-bit mask used for collision filtering. See comments for PxGroupsMask + +\param[in] actor The actor + +\return The group mask for the actor. + +@see PxSetGroupsMask() +*/ +PxGroupsMask PxGetGroupsMask(const PxActor& actor); + +/** +\brief Sets 64-bit mask used for collision filtering. See comments for PxGroupsMask + +\param[in] actor The actor +\param[in] mask The group mask to set for the actor. + +@see PxGetGroupsMask() +*/ +void PxSetGroupsMask(PxActor& actor, const PxGroupsMask& mask); + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/extensions/PxDefaultStreams.h b/sources/PhysX/PhysX/include/extensions/PxDefaultStreams.h new file mode 100644 index 00000000..0b33ec4c --- /dev/null +++ b/sources/PhysX/PhysX/include/extensions/PxDefaultStreams.h @@ -0,0 +1,149 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_EXTENSIONS_DEFAULT_STREAMS_H +#define PX_PHYSICS_EXTENSIONS_DEFAULT_STREAMS_H +/** \addtogroup extensions + @{ +*/ + +#include +#include "common/PxPhysXCommonConfig.h" +#include "foundation/PxIO.h" +#include "PxFoundation.h" + +typedef FILE* PxFileHandle; + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief default implementation of a memory write stream + +@see PxOutputStream +*/ + +class PxDefaultMemoryOutputStream: public PxOutputStream +{ +public: + PxDefaultMemoryOutputStream(PxAllocatorCallback &allocator = PxGetFoundation().getAllocatorCallback()); + virtual ~PxDefaultMemoryOutputStream(); + + virtual PxU32 write(const void* src, PxU32 count); + + virtual PxU32 getSize() const { return mSize; } + virtual PxU8* getData() const { return mData; } + +private: + PxDefaultMemoryOutputStream(const PxDefaultMemoryOutputStream&); + PxDefaultMemoryOutputStream& operator=(const PxDefaultMemoryOutputStream&); + + PxAllocatorCallback& mAllocator; + PxU8* mData; + PxU32 mSize; + PxU32 mCapacity; +}; + +/** +\brief default implementation of a memory read stream + +@see PxInputData +*/ + +class PxDefaultMemoryInputData: public PxInputData +{ +public: + PxDefaultMemoryInputData(PxU8* data, PxU32 length); + + virtual PxU32 read(void* dest, PxU32 count); + virtual PxU32 getLength() const; + virtual void seek(PxU32 pos); + virtual PxU32 tell() const; + +private: + PxU32 mSize; + const PxU8* mData; + PxU32 mPos; +}; + + + +/** +\brief default implementation of a file write stream + +@see PxOutputStream +*/ + +class PxDefaultFileOutputStream: public PxOutputStream +{ +public: + PxDefaultFileOutputStream(const char* name); + virtual ~PxDefaultFileOutputStream(); + + virtual PxU32 write(const void* src, PxU32 count); + virtual bool isValid(); +private: + PxFileHandle mFile; +}; + + +/** +\brief default implementation of a file read stream + +@see PxInputData +*/ + +class PxDefaultFileInputData: public PxInputData +{ +public: + PxDefaultFileInputData(const char* name); + virtual ~PxDefaultFileInputData(); + + virtual PxU32 read(void* dest, PxU32 count); + virtual void seek(PxU32 pos); + virtual PxU32 tell() const; + virtual PxU32 getLength() const; + + bool isValid() const; +private: + PxFileHandle mFile; + PxU32 mLength; +}; + +#if !PX_DOXYGEN +} +#endif + +/** @} */ + +#endif + diff --git a/sources/PhysX/PhysX/include/extensions/PxDistanceJoint.h b/sources/PhysX/PhysX/include/extensions/PxDistanceJoint.h new file mode 100644 index 00000000..ab6ae2d5 --- /dev/null +++ b/sources/PhysX/PhysX/include/extensions/PxDistanceJoint.h @@ -0,0 +1,269 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_DISTANCEJOINT_H +#define PX_DISTANCEJOINT_H +/** \addtogroup extensions + @{ +*/ + +#include "extensions/PxJoint.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxDistanceJoint; + +/** +\brief Create a distance Joint. + + \param[in] physics The physics SDK + \param[in] actor0 An actor to which the joint is attached. NULL may be used to attach the joint to a specific point in the world frame + \param[in] localFrame0 The position and orientation of the joint relative to actor0 + \param[in] actor1 An actor to which the joint is attached. NULL may be used to attach the joint to a specific point in the world frame + \param[in] localFrame1 The position and orientation of the joint relative to actor1 + +@see PxDistanceJoint +*/ +PxDistanceJoint* PxDistanceJointCreate(PxPhysics& physics, PxRigidActor* actor0, const PxTransform& localFrame0, PxRigidActor* actor1, const PxTransform& localFrame1); + + +/** +\brief flags for configuring the drive of a PxDistanceJoint + +@see PxDistanceJoint +*/ +struct PxDistanceJointFlag +{ + enum Enum + { + eMAX_DISTANCE_ENABLED = 1<<1, + eMIN_DISTANCE_ENABLED = 1<<2, + eSPRING_ENABLED = 1<<3 + }; +}; + +typedef PxFlags PxDistanceJointFlags; +PX_FLAGS_OPERATORS(PxDistanceJointFlag::Enum, PxU16) + +/** +\brief a joint that maintains an upper or lower bound (or both) on the distance between two points on different objects + +@see PxDistanceJointCreate PxJoint +*/ +class PxDistanceJoint : public PxJoint +{ +public: + + /** + \brief Return the current distance of the joint + */ + virtual PxReal getDistance() const = 0; + + /** + \brief Set the allowed minimum distance for the joint. + + The minimum distance must be no more than the maximum distance + + Default 0.0f + Range [0, PX_MAX_F32) + + \param[in] distance the minimum distance + + @see PxDistanceJoint::minDistance, PxDistanceJointFlag::eMIN_DISTANCE_ENABLED getMinDistance() + */ + virtual void setMinDistance(PxReal distance) = 0; + + /** + \brief Get the allowed minimum distance for the joint. + + \return the allowed minimum distance + + @see PxDistanceJoint::minDistance, PxDistanceJointFlag::eMIN_DISTANCE_ENABLED setMinDistance() + */ + virtual PxReal getMinDistance() const = 0; + + /** + \brief Set the allowed maximum distance for the joint. + + The maximum distance must be no less than the minimum distance. + + Default 0.0f + Range [0, PX_MAX_F32) + + \param[in] distance the maximum distance + + @see PxDistanceJoint::maxDistance, PxDistanceJointFlag::eMAX_DISTANCE_ENABLED getMinDistance() + */ + virtual void setMaxDistance(PxReal distance) = 0; + + /** + \brief Get the allowed maximum distance for the joint. + + \return the allowed maximum distance + + @see PxDistanceJoint::maxDistance, PxDistanceJointFlag::eMAX_DISTANCE_ENABLED setMaxDistance() + */ + virtual PxReal getMaxDistance() const = 0; + + /** + \brief Set the error tolerance of the joint. + + \param[in] tolerance the distance beyond the allowed range at which the joint becomes active + + @see PxDistanceJoint::tolerance, getTolerance() + */ + virtual void setTolerance(PxReal tolerance) = 0; + + /** + \brief Get the error tolerance of the joint. + + the distance beyond the joint's [min, max] range before the joint becomes active. + + Default 0.25f * PxTolerancesScale::length + Range (0, PX_MAX_F32) + + This value should be used to ensure that if the minimum distance is zero and the + spring function is in use, the rest length of the spring is non-zero. + + @see PxDistanceJoint::tolerance, setTolerance() + */ + virtual PxReal getTolerance() const = 0; + + /** + \brief Set the strength of the joint spring. + + The spring is used if enabled, and the distance exceeds the range [min-error, max+error]. + + Default 0.0f + Range [0, PX_MAX_F32) + + \param[in] stiffness the spring strength of the joint + + @see PxDistanceJointFlag::eSPRING_ENABLED getStiffness() + */ + virtual void setStiffness(PxReal stiffness) = 0; + + /** + \brief Get the strength of the joint spring. + + \return stiffness the spring strength of the joint + + @see PxDistanceJointFlag::eSPRING_ENABLED setStiffness() + */ + virtual PxReal getStiffness() const = 0; + + /** + \brief Set the damping of the joint spring. + + The spring is used if enabled, and the distance exceeds the range [min-error, max+error]. + + Default 0.0f + Range [0, PX_MAX_F32) + + \param[in] damping the degree of damping of the joint spring of the joint + + @see PxDistanceJointFlag::eSPRING_ENABLED setDamping() + */ + virtual void setDamping(PxReal damping) = 0; + + /** + \brief Get the damping of the joint spring. + + \return the degree of damping of the joint spring of the joint + + @see PxDistanceJointFlag::eSPRING_ENABLED setDamping() + */ + virtual PxReal getDamping() const = 0; + + /** + \brief Set the flags specific to the Distance Joint. + + Default PxDistanceJointFlag::eMAX_DISTANCE_ENABLED + + \param[in] flags The joint flags. + + @see PxDistanceJointFlag setFlag() getFlags() + */ + virtual void setDistanceJointFlags(PxDistanceJointFlags flags) = 0; + + /** + \brief Set a single flag specific to a Distance Joint to true or false. + + \param[in] flag The flag to set or clear. + \param[in] value the value to which to set the flag + + @see PxDistanceJointFlag, getFlags() setFlags() + */ + virtual void setDistanceJointFlag(PxDistanceJointFlag::Enum flag, bool value) = 0; + + /** + \brief Get the flags specific to the Distance Joint. + + \return the joint flags + + @see PxDistanceJoint::flags, PxDistanceJointFlag setFlag() setFlags() + */ + virtual PxDistanceJointFlags getDistanceJointFlags() const = 0; + + /** + \brief Returns string name of PxDistanceJoint, used for serialization + */ + virtual const char* getConcreteTypeName() const { return "PxDistanceJoint"; } + +protected: + + //serialization + + /** + \brief Constructor + */ + PX_INLINE PxDistanceJoint(PxType concreteType, PxBaseFlags baseFlags) : PxJoint(concreteType, baseFlags) {} + + /** + \brief Deserialization constructor + */ + PX_INLINE PxDistanceJoint(PxBaseFlags baseFlags) : PxJoint(baseFlags) {} + + /** + \brief Returns whether a given type name matches with the type of this instance + */ + virtual bool isKindOf(const char* name) const { return !::strcmp("PxDistanceJoint", name) || PxJoint::isKindOf(name); } + + //~serialization +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/extensions/PxExtensionsAPI.h b/sources/PhysX/PhysX/include/extensions/PxExtensionsAPI.h new file mode 100644 index 00000000..46142bc9 --- /dev/null +++ b/sources/PhysX/PhysX/include/extensions/PxExtensionsAPI.h @@ -0,0 +1,88 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_EXTENSIONS_API_H +#define PX_EXTENSIONS_API_H +/** \addtogroup extensions + @{ +*/ + +#include "foundation/PxErrorCallback.h" +#include "extensions/PxDefaultAllocator.h" +#include "extensions/PxConstraintExt.h" +#include "extensions/PxDistanceJoint.h" +#include "extensions/PxContactJoint.h" +#include "extensions/PxFixedJoint.h" +#include "extensions/PxPrismaticJoint.h" +#include "extensions/PxRevoluteJoint.h" +#include "extensions/PxSphericalJoint.h" +#include "extensions/PxD6Joint.h" +#include "extensions/PxDefaultSimulationFilterShader.h" +#include "extensions/PxDefaultErrorCallback.h" +#include "extensions/PxDefaultStreams.h" +#include "extensions/PxRigidActorExt.h" +#include "extensions/PxRigidBodyExt.h" +#include "extensions/PxShapeExt.h" +#include "extensions/PxTriangleMeshExt.h" +#include "extensions/PxSerialization.h" +#include "extensions/PxDefaultCpuDispatcher.h" +#include "extensions/PxSmoothNormals.h" +#include "extensions/PxSimpleFactory.h" +#include "extensions/PxStringTableExt.h" +#include "extensions/PxBroadPhaseExt.h" +#include "extensions/PxMassProperties.h" +#include "extensions/PxSceneQueryExt.h" + +/** \brief Initialize the PhysXExtensions library. + +This should be called before calling any functions or methods in extensions which may require allocation. +\note This function does not need to be called before creating a PxDefaultAllocator object. + +\param physics a PxPhysics object +\param pvd an PxPvd (PhysX Visual Debugger) object + +@see PxCloseExtensions PxFoundation PxPhysics +*/ + +PX_C_EXPORT bool PX_CALL_CONV PxInitExtensions(physx::PxPhysics& physics, physx::PxPvd* pvd); + +/** \brief Shut down the PhysXExtensions library. + +This function should be called to cleanly shut down the PhysXExtensions library before application exit. + +\note This function is required to be called to release foundation usage. + +@see PxInitExtensions +*/ + +PX_C_EXPORT void PX_CALL_CONV PxCloseExtensions(); + +/** @} */ +#endif // PX_EXTENSIONS_API_H diff --git a/sources/PhysX/PhysX/include/extensions/PxFixedJoint.h b/sources/PhysX/PhysX/include/extensions/PxFixedJoint.h new file mode 100644 index 00000000..e68aaa19 --- /dev/null +++ b/sources/PhysX/PhysX/include/extensions/PxFixedJoint.h @@ -0,0 +1,159 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_FIXEDJOINT_H +#define PX_FIXEDJOINT_H +/** \addtogroup extensions + @{ +*/ + +#include "extensions/PxJoint.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxFixedJoint; + +/** +\brief Create a fixed joint. + + \param[in] physics The physics SDK + \param[in] actor0 An actor to which the joint is attached. NULL may be used to attach the joint to a specific point in the world frame + \param[in] localFrame0 The position and orientation of the joint relative to actor0 + \param[in] actor1 An actor to which the joint is attached. NULL may be used to attach the joint to a specific point in the world frame + \param[in] localFrame1 The position and orientation of the joint relative to actor1 + +@see PxFixedJoint +*/ +PxFixedJoint* PxFixedJointCreate(PxPhysics& physics, PxRigidActor* actor0, const PxTransform& localFrame0, PxRigidActor* actor1, const PxTransform& localFrame1); + +/** + \brief A fixed joint permits no relative movement between two bodies. ie the bodies are glued together. + + \image html fixedJoint.png + + @see PxFixedJointCreate() PxJoint +*/ +class PxFixedJoint : public PxJoint +{ +public: + + /** + \brief Set the linear tolerance threshold for projection. Projection is enabled if PxConstraintFlag::ePROJECTION + is set for the joint. + + If the joint separates by more than this distance along its locked degrees of freedom, the solver + will move the bodies to close the distance. + + Setting a very small tolerance may result in simulation jitter or other artifacts. + + Sometimes it is not possible to project (for example when the joints form a cycle). + + Range: [0, PX_MAX_F32)
+ Default: 1e10f + + \param[in] tolerance the linear tolerance threshold + + @see getProjectionLinearTolerance() PxJoint::setConstraintFlags() PxConstraintFlag::ePROJECTION + */ + virtual void setProjectionLinearTolerance(PxReal tolerance) = 0; + + /** + \brief Get the linear tolerance threshold for projection. + + \return the linear tolerance threshold + + @see setProjectionLinearTolerance() PxJoint::setConstraintFlag() + */ + virtual PxReal getProjectionLinearTolerance() const = 0; + + /** + \brief Set the angular tolerance threshold for projection. Projection is enabled if + PxConstraintFlag::ePROJECTION is set for the joint. + + If the joint deviates by more than this angle around its locked angular degrees of freedom, + the solver will move the bodies to close the angle. + + Setting a very small tolerance may result in simulation jitter or other artifacts. + + Sometimes it is not possible to project (for example when the joints form a cycle). + + Range: [0,Pi]
+ Default: Pi + + \param[in] tolerance the angular tolerance threshold in radians + + @see getProjectionAngularTolerance() PxJoint::setConstraintFlag() PxConstraintFlag::ePROJECTION + */ + virtual void setProjectionAngularTolerance(PxReal tolerance) = 0; + + /** + \brief Get the angular tolerance threshold for projection. + + \return the angular tolerance threshold in radians + + @see setProjectionAngularTolerance() + */ + virtual PxReal getProjectionAngularTolerance() const = 0; + + /** + \brief Returns string name of PxFixedJoint, used for serialization + */ + virtual const char* getConcreteTypeName() const { return "PxFixedJoint"; } + +protected: + + //serialization + + /** + \brief Constructor + */ + PX_INLINE PxFixedJoint(PxType concreteType, PxBaseFlags baseFlags) : PxJoint(concreteType, baseFlags) {} + + /** + \brief Deserialization constructor + */ + PX_INLINE PxFixedJoint(PxBaseFlags baseFlags) : PxJoint(baseFlags) {} + + /** + \brief Returns whether a given type name matches with the type of this instance + */ + virtual bool isKindOf(const char* name) const { return !::strcmp("PxFixedJoint", name) || PxJoint::isKindOf(name); } + + //~serialization +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/extensions/PxJoint.h b/sources/PhysX/PhysX/include/extensions/PxJoint.h new file mode 100644 index 00000000..43e8785d --- /dev/null +++ b/sources/PhysX/PhysX/include/extensions/PxJoint.h @@ -0,0 +1,419 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_JOINTCONSTRAINT_H +#define PX_JOINTCONSTRAINT_H +/** \addtogroup extensions + @{ +*/ + +#include "foundation/PxTransform.h" +#include "PxRigidActor.h" +#include "PxConstraint.h" +#include "common/PxBase.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxRigidActor; +class PxScene; +class PxPhysics; +class PxConstraint; + +/** +\brief an enumeration of PhysX' built-in joint types + +@see PxJoint +*/ +struct PxJointConcreteType +{ + enum Enum + { + eSPHERICAL = PxConcreteType::eFIRST_PHYSX_EXTENSION, + eREVOLUTE, + ePRISMATIC, + eFIXED, + eDISTANCE, + eD6, + eCONTACT, + eLast + }; +}; + +PX_DEFINE_TYPEINFO(PxJoint, PxConcreteType::eUNDEFINED) +PX_DEFINE_TYPEINFO(PxD6Joint, PxJointConcreteType::eD6) +PX_DEFINE_TYPEINFO(PxDistanceJoint, PxJointConcreteType::eDISTANCE) +PX_DEFINE_TYPEINFO(PxContactJoint, PxJointConcreteType::eCONTACT) +PX_DEFINE_TYPEINFO(PxFixedJoint, PxJointConcreteType::eFIXED) +PX_DEFINE_TYPEINFO(PxPrismaticJoint, PxJointConcreteType::ePRISMATIC) +PX_DEFINE_TYPEINFO(PxRevoluteJoint, PxJointConcreteType::eREVOLUTE) +PX_DEFINE_TYPEINFO(PxSphericalJoint, PxJointConcreteType::eSPHERICAL) + + +/** +\brief an enumeration for specifying one or other of the actors referenced by a joint + +@see PxJoint +*/ + +struct PxJointActorIndex +{ + enum Enum + { + eACTOR0, + eACTOR1, + COUNT + }; +}; + +/** +\brief a base interface providing common functionality for PhysX joints +*/ + +class PxJoint : public PxBase +{ +//= ATTENTION! ===================================================================================== +// Changing the data layout of this class breaks the binary serialization format. See comments for +// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData +// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION +// accordingly. +//================================================================================================== +public: + + /** + \brief Set the actors for this joint. + + An actor may be NULL to indicate the world frame. At most one of the actors may be NULL. + + \param[in] actor0 the first actor. + \param[in] actor1 the second actor + + @see getActors() + */ + virtual void setActors(PxRigidActor* actor0, PxRigidActor* actor1) = 0; + + /** + \brief Get the actors for this joint. + + \param[out] actor0 the first actor. + \param[out] actor1 the second actor + + @see setActors() + */ + virtual void getActors(PxRigidActor*& actor0, PxRigidActor*& actor1) const = 0; + + /** + \brief Set the joint local pose for an actor. + + This is the relative pose which locates the joint frame relative to the actor. + + \param[in] actor 0 for the first actor, 1 for the second actor. + \param[in] localPose the local pose for the actor this joint + + @see getLocalPose() + */ + virtual void setLocalPose(PxJointActorIndex::Enum actor, const PxTransform& localPose) = 0; + + /** + \brief get the joint local pose for an actor. + + \param[in] actor 0 for the first actor, 1 for the second actor. + + return the local pose for this joint + + @see setLocalPose() + */ + virtual PxTransform getLocalPose(PxJointActorIndex::Enum actor) const = 0; + + /** + \brief get the relative pose for this joint + + This function returns the pose of the joint frame of actor1 relative to actor0 + + */ + virtual PxTransform getRelativeTransform() const = 0; + + /** + \brief get the relative linear velocity of the joint + + This function returns the linear velocity of the origin of the constraint frame of actor1, relative to the origin of the constraint + frame of actor0. The value is returned in the constraint frame of actor0 + */ + virtual PxVec3 getRelativeLinearVelocity() const = 0; + + /** + \brief get the relative angular velocity of the joint + + This function returns the angular velocity of actor1 relative to actor0. The value is returned in the constraint frame of actor0 + */ + virtual PxVec3 getRelativeAngularVelocity() const = 0; + + /** + \brief set the break force for this joint. + + if the constraint force or torque on the joint exceeds the specified values, the joint will break, + at which point it will not constrain the two actors and the flag PxConstraintFlag::eBROKEN will be set. The + force and torque are measured in the joint frame of the first actor + + \param[in] force the maximum force the joint can apply before breaking + \param[in] torque the maximum torque the joint can apply before breaking + */ + virtual void setBreakForce(PxReal force, PxReal torque) = 0; + + /** + \brief get the break force for this joint. + + \param[out] force the maximum force the joint can apply before breaking + \param[out] torque the maximum torque the joint can apply before breaking + + @see setBreakForce() + */ + virtual void getBreakForce(PxReal& force, PxReal& torque) const = 0; + + /** + \brief set the constraint flags for this joint. + + \param[in] flags the constraint flags + + @see PxConstraintFlag + */ + virtual void setConstraintFlags(PxConstraintFlags flags) = 0; + + /** + \brief set a constraint flags for this joint to a specified value. + + \param[in] flag the constraint flag + \param[in] value the value to which to set the flag + + @see PxConstraintFlag + */ + virtual void setConstraintFlag(PxConstraintFlag::Enum flag, bool value) = 0; + + /** + \brief get the constraint flags for this joint. + + \return the constraint flags + + @see PxConstraintFlag + */ + virtual PxConstraintFlags getConstraintFlags() const = 0; + + /** + \brief set the inverse mass scale for actor0. + + \param[in] invMassScale the scale to apply to the inverse mass of actor 0 for resolving this constraint + + @see getInvMassScale0 + */ + virtual void setInvMassScale0(PxReal invMassScale) = 0; + + /** + \brief get the inverse mass scale for actor0. + + \return inverse mass scale for actor0 + + @see setInvMassScale0 + */ + virtual PxReal getInvMassScale0() const = 0; + + /** + \brief set the inverse inertia scale for actor0. + + \param[in] invInertiaScale the scale to apply to the inverse inertia of actor0 for resolving this constraint + + @see getInvMassScale0 + */ + virtual void setInvInertiaScale0(PxReal invInertiaScale) = 0; + + /** + \brief get the inverse inertia scale for actor0. + + \return inverse inertia scale for actor0 + + @see setInvInertiaScale0 + */ + virtual PxReal getInvInertiaScale0() const = 0; + + /** + \brief set the inverse mass scale for actor1. + + \param[in] invMassScale the scale to apply to the inverse mass of actor 1 for resolving this constraint + + @see getInvMassScale1 + */ + virtual void setInvMassScale1(PxReal invMassScale) = 0; + + /** + \brief get the inverse mass scale for actor1. + + \return inverse mass scale for actor1 + + @see setInvMassScale1 + */ + virtual PxReal getInvMassScale1() const = 0; + + /** + \brief set the inverse inertia scale for actor1. + + \param[in] invInertiaScale the scale to apply to the inverse inertia of actor1 for resolving this constraint + + @see getInvInertiaScale1 + */ + virtual void setInvInertiaScale1(PxReal invInertiaScale) = 0; + + /** + \brief get the inverse inertia scale for actor1. + + \return inverse inertia scale for actor1 + + @see setInvInertiaScale1 + */ + virtual PxReal getInvInertiaScale1() const = 0; + + /** + \brief Retrieves the PxConstraint corresponding to this joint. + + This can be used to determine, among other things, the force applied at the joint. + + \return the constraint + */ + virtual PxConstraint* getConstraint() const = 0; + + /** + \brief Sets a name string for the object that can be retrieved with getName(). + + This is for debugging and is not used by the SDK. The string is not copied by the SDK, + only the pointer is stored. + + \param[in] name String to set the objects name to. + + @see getName() + */ + virtual void setName(const char* name) = 0; + + /** + \brief Retrieves the name string set with setName(). + + \return Name string associated with object. + + @see setName() + */ + virtual const char* getName() const = 0; + + /** + \brief Deletes the joint. + + \note This call does not wake up the connected rigid bodies. + */ + virtual void release() = 0; + + /** + \brief Retrieves the scene which this joint belongs to. + + \return Owner Scene. NULL if not part of a scene. + + @see PxScene + */ + virtual PxScene* getScene() const = 0; + + void* userData; //!< user can assign this to whatever, usually to create a 1:1 relationship with a user object. + + //serialization + + /** + \brief Put class meta data in stream, used for serialization + */ + static void getBinaryMetaData(PxOutputStream& stream); + + //~serialization + +protected: + virtual ~PxJoint() {} + + //serialization + + /** + \brief Constructor + */ + PX_INLINE PxJoint(PxType concreteType, PxBaseFlags baseFlags) : PxBase(concreteType, baseFlags), userData(NULL) {} + + /** + \brief Deserialization constructor + */ + PX_INLINE PxJoint(PxBaseFlags baseFlags) : PxBase(baseFlags) {} + + /** + \brief Returns whether a given type name matches with the type of this instance + */ + virtual bool isKindOf(const char* name) const { return !::strcmp("PxJoint", name) || PxBase::isKindOf(name); } + + //~serialization +}; + +class PxSpring +{ +//= ATTENTION! ===================================================================================== +// Changing the data layout of this class breaks the binary serialization format. See comments for +// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData +// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION +// accordingly. +//================================================================================================== +public: + + PxReal stiffness; //!< the spring strength of the drive: that is, the force proportional to the position error + PxReal damping; //!< the damping strength of the drive: that is, the force proportional to the velocity error + + PxSpring(PxReal stiffness_, PxReal damping_): stiffness(stiffness_), damping(damping_) {} +}; + + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** \brief Helper function to setup a joint's global frame + + This replaces the following functions from previous SDK versions: + + void NxJointDesc::setGlobalAnchor(const NxVec3& wsAnchor); + void NxJointDesc::setGlobalAxis(const NxVec3& wsAxis); + + The function sets the joint's localPose using world-space input parameters. + + \param[in] wsAnchor Global frame anchor point. Range: position vector + \param[in] wsAxis Global frame axis. Range: direction vector + \param[in,out] joint Joint having its global frame set. +*/ + +PX_C_EXPORT void PX_CALL_CONV PxSetJointGlobalFrame(physx::PxJoint& joint, const physx::PxVec3* wsAnchor, const physx::PxVec3* wsAxis); + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/extensions/PxJointLimit.h b/sources/PhysX/PhysX/include/extensions/PxJointLimit.h new file mode 100644 index 00000000..2f89138a --- /dev/null +++ b/sources/PhysX/PhysX/include/extensions/PxJointLimit.h @@ -0,0 +1,566 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_EXTENSIONS_JOINT_LIMIT +#define PX_EXTENSIONS_JOINT_LIMIT +/** \addtogroup extensions + @{ +*/ + +#include "foundation/PxMath.h" +#include "common/PxTolerancesScale.h" +#include "extensions/PxJoint.h" +#include "PxPhysXConfig.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief Describes the parameters for a joint limit. + +Limits are enabled or disabled by setting flags or other configuration parameters joints, see the +documentation for specific joint types for details. +*/ +class PxJointLimitParameters +{ +//= ATTENTION! ===================================================================================== +// Changing the data layout of this class breaks the binary serialization format. See comments for +// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData +// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION +// accordingly. +//================================================================================================== +public: + /** + \brief Controls the amount of bounce when the joint hits a limit. + + A restitution value of 1.0 causes the joint to bounce back with the velocity which it hit the limit. + A value of zero causes the joint to stop dead. + + In situations where the joint has many locked DOFs (e.g. 5) the restitution may not be applied + correctly. This is due to a limitation in the solver which causes the restitution velocity to become zero + as the solver enforces constraints on the other DOFs. + + This limitation applies to both angular and linear limits, however it is generally most apparent with limited + angular DOFs. Disabling joint projection and increasing the solver iteration count may improve this behavior + to some extent. + + Also, combining soft joint limits with joint drives driving against those limits may affect stability. + + Range: [0,1]
+ Default: 0.0 + */ + PxReal restitution; + + /** + determines the minimum impact velocity which will cause the joint to bounce + */ + PxReal bounceThreshold; + + /** + \brief if greater than zero, the limit is soft, i.e. a spring pulls the joint back to the limit + + Range: [0, PX_MAX_F32)
+ Default: 0.0 + */ + PxReal stiffness; + + /** + \brief if spring is greater than zero, this is the damping of the limit spring + + Range: [0, PX_MAX_F32)
+ Default: 0.0 + */ + PxReal damping; + + /** + \brief the distance inside the limit value at which the limit will be considered to be active by the + solver. As this value is made larger, the limit becomes active more quickly. It thus becomes less + likely to violate the extents of the limit, but more expensive. + + The contact distance should be less than the limit angle or distance, and in the case of a pair limit, + less than half the distance between the upper and lower bounds. Exceeding this value will result in + the limit being active all the time. + + Making this value too small can result in jitter around the limit. + + Default: depends on the joint + + @see PxPhysics::getTolerancesScale() + */ + PxReal contactDistance; + + PxJointLimitParameters() : + restitution (0.0f), + bounceThreshold (0.0f), + stiffness (0.0f), + damping (0.0f), + contactDistance (0.0f) + { + } + + PxJointLimitParameters(const PxJointLimitParameters& p) : + restitution (p.restitution), + bounceThreshold (p.bounceThreshold), + stiffness (p.stiffness), + damping (p.damping), + contactDistance (p.contactDistance) + { + } + + /** + \brief Returns true if the current settings are valid. + + \return true if the current settings are valid + */ + PX_INLINE bool isValid() const + { + return PxIsFinite(restitution) && restitution >= 0 && restitution <= 1 && + PxIsFinite(stiffness) && stiffness >= 0 && + PxIsFinite(damping) && damping >= 0 && + PxIsFinite(bounceThreshold) && bounceThreshold >= 0 && + PxIsFinite(contactDistance) && contactDistance >= 0; + } + + PX_INLINE bool isSoft() const + { + return damping>0 || stiffness>0; + } + +protected: + ~PxJointLimitParameters() {} +}; + + +/** +\brief Describes a one-sided linear limit. +*/ +class PxJointLinearLimit : public PxJointLimitParameters +{ +//= ATTENTION! ===================================================================================== +// Changing the data layout of this class breaks the binary serialization format. See comments for +// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData +// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION +// accordingly. +//================================================================================================== +public: + /** + \brief the extent of the limit. + + Range: (0, PX_MAX_F32)
+ Default: PX_MAX_F32 + */ + PxReal value; + + /** + \brief construct a linear hard limit + + \param[in] scale A PxTolerancesScale struct. Should be the same as used when creating the PxPhysics object. + \param[in] extent The extent of the limit + \param[in] contactDist The distance from the limit at which it becomes active. Default is 0.01f scaled by the tolerance length scale + + @see PxJointLimitParameters PxTolerancesScale + */ + PxJointLinearLimit(const PxTolerancesScale& scale, PxReal extent, PxReal contactDist = -1.0f) + : value(extent) + { + PxJointLimitParameters::contactDistance = contactDist == -1.0f ? 0.01f*scale.length : contactDist; + } + + /** + \brief construct a linear soft limit + + \param[in] extent the extent of the limit + \param[in] spring the stiffness and damping parameters for the limit spring + + @see PxJointLimitParameters PxTolerancesScale + */ + PxJointLinearLimit(PxReal extent, const PxSpring& spring) : value(extent) + { + stiffness = spring.stiffness; + damping = spring.damping; + } + + /** + \brief Returns true if the limit is valid + + \return true if the current settings are valid + */ + PX_INLINE bool isValid() const + { + return PxJointLimitParameters::isValid() && + PxIsFinite(value) && + value > 0.0f; + } +}; + + +/** +\brief Describes a two-sided limit. +*/ +class PxJointLinearLimitPair : public PxJointLimitParameters +{ +//= ATTENTION! ===================================================================================== +// Changing the data layout of this class breaks the binary serialization format. See comments for +// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData +// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION +// accordingly. +//================================================================================================== +public: + /** + \brief the range of the limit. The upper limit must be no lower than the + lower limit, and if they are equal the limited degree of freedom will be treated as locked. + + Range: See the joint on which the limit is used for details
+ Default: lower = -PX_MAX_F32/3, upper = PX_MAX_F32/3 + */ + PxReal upper, lower; + + /** + \brief Construct a linear hard limit pair. The lower distance value must be less than the upper distance value. + + \param[in] scale A PxTolerancesScale struct. Should be the same as used when creating the PxPhysics object. + \param[in] lowerLimit The lower distance of the limit + \param[in] upperLimit The upper distance of the limit + \param[in] contactDist The distance from the limit at which it becomes active. Default is the lesser of 0.01f scaled by the tolerance length scale, and 0.49 * (upperLimit - lowerLimit) + + @see PxJointLimitParameters PxTolerancesScale + */ + PxJointLinearLimitPair(const PxTolerancesScale& scale, PxReal lowerLimit = -PX_MAX_F32/3.0f, PxReal upperLimit = PX_MAX_F32/3.0f, PxReal contactDist = -1.0f) : + upper(upperLimit), + lower(lowerLimit) + { + PxJointLimitParameters::contactDistance = contactDist == -1.0f ? PxMin(scale.length * 0.01f, (upperLimit*0.49f-lowerLimit*0.49f)) : contactDist; + bounceThreshold = 2.0f*scale.length; + } + + /** + \brief construct a linear soft limit pair + + \param[in] lowerLimit The lower distance of the limit + \param[in] upperLimit The upper distance of the limit + \param[in] spring The stiffness and damping parameters of the limit spring + + @see PxJointLimitParameters PxTolerancesScale + */ + PxJointLinearLimitPair(PxReal lowerLimit, PxReal upperLimit, const PxSpring& spring) : + upper(upperLimit), + lower(lowerLimit) + { + stiffness = spring.stiffness; + damping = spring.damping; + } + + /** + \brief Returns true if the limit is valid. + + \return true if the current settings are valid + */ + PX_INLINE bool isValid() const + { + return PxJointLimitParameters::isValid() && + PxIsFinite(upper) && PxIsFinite(lower) && upper >= lower && + PxIsFinite(upper - lower); + } +}; + + +class PxJointAngularLimitPair : public PxJointLimitParameters +{ +//= ATTENTION! ===================================================================================== +// Changing the data layout of this class breaks the binary serialization format. See comments for +// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData +// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION +// accordingly. +//================================================================================================== +public: + /** + \brief the range of the limit. The upper limit must be no lower than the lower limit. + + Unit: Angular: Radians + Range: See the joint on which the limit is used for details
+ Default: lower = -PI/2, upper = PI/2 + */ + PxReal upper, lower; + + /** + \brief construct an angular hard limit pair. + + The lower value must be less than the upper value. + + \param[in] lowerLimit The lower angle of the limit + \param[in] upperLimit The upper angle of the limit + \param[in] contactDist The distance from the limit at which it becomes active. Default is the lesser of 0.1 radians, and 0.49 * (upperLimit - lowerLimit) + + @see PxJointLimitParameters + */ + PxJointAngularLimitPair(PxReal lowerLimit, PxReal upperLimit, PxReal contactDist = -1.0f) : + upper(upperLimit), + lower(lowerLimit) + { + PxJointLimitParameters::contactDistance = contactDist ==-1.0f ? PxMin(0.1f, 0.49f*(upperLimit-lowerLimit)) : contactDist; + bounceThreshold = 0.5f; + } + + /** + \brief construct an angular soft limit pair. + + The lower value must be less than the upper value. + + \param[in] lowerLimit The lower angle of the limit + \param[in] upperLimit The upper angle of the limit + \param[in] spring The stiffness and damping of the limit spring + + @see PxJointLimitParameters + */ + PxJointAngularLimitPair(PxReal lowerLimit, PxReal upperLimit, const PxSpring& spring) : + upper(upperLimit), + lower(lowerLimit) + { + stiffness = spring.stiffness; + damping = spring.damping; + } + + /** + \brief Returns true if the limit is valid. + + \return true if the current settings are valid + */ + PX_INLINE bool isValid() const + { + return PxJointLimitParameters::isValid() && + PxIsFinite(upper) && PxIsFinite(lower) && upper >= lower; + } +}; + +/** +\brief Describes an elliptical conical joint limit. Note that very small or highly elliptical limit cones may +result in jitter. + +@see PxD6Joint PxSphericalJoint +*/ +class PxJointLimitCone : public PxJointLimitParameters +{ +//= ATTENTION! ===================================================================================== +// Changing the data layout of this class breaks the binary serialization format. See comments for +// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData +// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION +// accordingly. +//================================================================================================== +public: + /** + \brief the maximum angle from the Y axis of the constraint frame. + + Unit: Angular: Radians + Range: Angular: (0,PI)
+ Default: PI/2 + */ + PxReal yAngle; + + /** + \brief the maximum angle from the Z-axis of the constraint frame. + + Unit: Angular: Radians + Range: Angular: (0,PI)
+ Default: PI/2 + */ + PxReal zAngle; + + /** + \brief Construct a cone hard limit. + + \param[in] yLimitAngle The limit angle from the Y-axis of the constraint frame + \param[in] zLimitAngle The limit angle from the Z-axis of the constraint frame + \param[in] contactDist The distance from the limit at which it becomes active. Default is the lesser of 0.1 radians, and 0.49 * the lower of the limit angles + + @see PxJointLimitParameters + */ + PxJointLimitCone(PxReal yLimitAngle, PxReal zLimitAngle, PxReal contactDist = -1.0f) : + yAngle(yLimitAngle), + zAngle(zLimitAngle) + { + PxJointLimitParameters::contactDistance = contactDist == -1.0f ? PxMin(0.1f, PxMin(yLimitAngle, zLimitAngle)*0.49f) : contactDist; + bounceThreshold = 0.5f; + } + + /** + \brief Construct a cone soft limit. + + \param[in] yLimitAngle The limit angle from the Y-axis of the constraint frame + \param[in] zLimitAngle The limit angle from the Z-axis of the constraint frame + \param[in] spring The stiffness and damping of the limit spring + + @see PxJointLimitParameters + */ + PxJointLimitCone(PxReal yLimitAngle, PxReal zLimitAngle, const PxSpring& spring) : + yAngle(yLimitAngle), + zAngle(zLimitAngle) + { + stiffness = spring.stiffness; + damping = spring.damping; + } + + /** + \brief Returns true if the limit is valid. + + \return true if the current settings are valid + */ + PX_INLINE bool isValid() const + { + return PxJointLimitParameters::isValid() && + PxIsFinite(yAngle) && yAngle>0 && yAngle0 && zAngleUnit: Angular: Radians + Range: Angular: (-PI,PI)
+ Default: -PI/2 + */ + PxReal yAngleMin; + + /** + \brief the maximum angle from the Y axis of the constraint frame. + + Unit: Angular: Radians + Range: Angular: (-PI,PI)
+ Default: PI/2 + */ + PxReal yAngleMax; + + /** + \brief the minimum angle from the Z-axis of the constraint frame. + + Unit: Angular: Radians + Range: Angular: (-PI,PI)
+ Default: -PI/2 + */ + PxReal zAngleMin; + + /** + \brief the maximum angle from the Z-axis of the constraint frame. + + Unit: Angular: Radians + Range: Angular: (-PI,PI)
+ Default: PI/2 + */ + PxReal zAngleMax; + + /** + \brief Construct a pyramid hard limit. + + \param[in] yLimitAngleMin The minimum limit angle from the Y-axis of the constraint frame + \param[in] yLimitAngleMax The maximum limit angle from the Y-axis of the constraint frame + \param[in] zLimitAngleMin The minimum limit angle from the Z-axis of the constraint frame + \param[in] zLimitAngleMax The maximum limit angle from the Z-axis of the constraint frame + \param[in] contactDist The distance from the limit at which it becomes active. Default is the lesser of 0.1 radians, and 0.49 * the lower of the limit angles + + @see PxJointLimitParameters + */ + PxJointLimitPyramid(PxReal yLimitAngleMin, PxReal yLimitAngleMax, PxReal zLimitAngleMin, PxReal zLimitAngleMax, PxReal contactDist = -1.0f) : + yAngleMin(yLimitAngleMin), + yAngleMax(yLimitAngleMax), + zAngleMin(zLimitAngleMin), + zAngleMax(zLimitAngleMax) + { + if(contactDist == -1.0f) + { + const PxReal contactDistY = PxMin(0.1f, 0.49f*(yLimitAngleMax - yLimitAngleMin)); + const PxReal contactDistZ = PxMin(0.1f, 0.49f*(zLimitAngleMax - zLimitAngleMin)); + PxJointLimitParameters::contactDistance = contactDist == PxMin(contactDistY, contactDistZ); + } + else + { + PxJointLimitParameters::contactDistance = contactDist; + } + + bounceThreshold = 0.5f; + } + + /** + \brief Construct a pyramid soft limit. + + \param[in] yLimitAngleMin The minimum limit angle from the Y-axis of the constraint frame + \param[in] yLimitAngleMax The maximum limit angle from the Y-axis of the constraint frame + \param[in] zLimitAngleMin The minimum limit angle from the Z-axis of the constraint frame + \param[in] zLimitAngleMax The maximum limit angle from the Z-axis of the constraint frame + \param[in] spring The stiffness and damping of the limit spring + + @see PxJointLimitParameters + */ + PxJointLimitPyramid(PxReal yLimitAngleMin, PxReal yLimitAngleMax, PxReal zLimitAngleMin, PxReal zLimitAngleMax, const PxSpring& spring) : + yAngleMin(yLimitAngleMin), + yAngleMax(yLimitAngleMax), + zAngleMin(zLimitAngleMin), + zAngleMax(zLimitAngleMax) + { + stiffness = spring.stiffness; + damping = spring.damping; + } + + /** + \brief Returns true if the limit is valid. + + \return true if the current settings are valid + */ + PX_INLINE bool isValid() const + { + return PxJointLimitParameters::isValid() && + PxIsFinite(yAngleMin) && yAngleMin>-PxPi && yAngleMin-PxPi && yAngleMax-PxPi && zAngleMin-PxPi && zAngleMax=yAngleMin && zAngleMax>=zAngleMin; + } +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/extensions/PxMassProperties.h b/sources/PhysX/PhysX/include/extensions/PxMassProperties.h new file mode 100644 index 00000000..9f44bf1e --- /dev/null +++ b/sources/PhysX/PhysX/include/extensions/PxMassProperties.h @@ -0,0 +1,335 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_EXTENSIONS_MASS_PROPERTIES_H +#define PX_PHYSICS_EXTENSIONS_MASS_PROPERTIES_H +/** \addtogroup extensions + @{ +*/ + +#include "PxPhysXConfig.h" +#include "foundation/PxMath.h" +#include "foundation/PxMathUtils.h" +#include "foundation/PxVec3.h" +#include "foundation/PxMat33.h" +#include "foundation/PxQuat.h" +#include "foundation/PxTransform.h" +#include "geometry/PxGeometry.h" +#include "geometry/PxBoxGeometry.h" +#include "geometry/PxSphereGeometry.h" +#include "geometry/PxCapsuleGeometry.h" +#include "geometry/PxConvexMeshGeometry.h" +#include "geometry/PxConvexMesh.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief Utility class to compute and manipulate mass and inertia tensor properties. + +In most cases #PxRigidBodyExt::updateMassAndInertia(), #PxRigidBodyExt::setMassAndUpdateInertia() should be enough to +setup the mass properties of a rigid body. This utility class targets users that need to customize the mass properties +computation. +*/ +class PxMassProperties +{ +public: + /** + \brief Default constructor. + */ + PX_FORCE_INLINE PxMassProperties() : inertiaTensor(PxIdentity), centerOfMass(0.0f), mass(1.0f) {} + + /** + \brief Construct from individual elements. + */ + PX_FORCE_INLINE PxMassProperties(const PxReal m, const PxMat33& inertiaT, const PxVec3& com) : inertiaTensor(inertiaT), centerOfMass(com), mass(m) {} + + /** + \brief Compute mass properties based on a provided geometry structure. + + This constructor assumes the geometry has a density of 1. Mass and inertia tensor scale linearly with density. + + \param[in] geometry The geometry to compute the mass properties for. Supported geometry types are: sphere, box, capsule and convex mesh. + */ + PxMassProperties(const PxGeometry& geometry) + { + switch (geometry.getType()) + { + case PxGeometryType::eSPHERE: + { + const PxSphereGeometry& s = static_cast(geometry); + mass = (4.0f / 3.0f) * PxPi * s.radius * s.radius * s.radius; + inertiaTensor = PxMat33::createDiagonal(PxVec3(2.0f / 5.0f * mass * s.radius * s.radius)); + centerOfMass = PxVec3(0.0f); + } + break; + + case PxGeometryType::eBOX: + { + const PxBoxGeometry& b = static_cast(geometry); + mass = b.halfExtents.x * b.halfExtents.y * b.halfExtents.z * 8.0f; + PxVec3 d2 = b.halfExtents.multiply(b.halfExtents); + inertiaTensor = PxMat33::createDiagonal(PxVec3(d2.y + d2.z, d2.x + d2.z, d2.x + d2.y)) * (mass * 1.0f / 3.0f); + centerOfMass = PxVec3(0.0f); + } + break; + + case PxGeometryType::eCAPSULE: + { + const PxCapsuleGeometry& c = static_cast(geometry); + PxReal r = c.radius, h = c.halfHeight; + mass = ((4.0f / 3.0f) * r + 2 * c.halfHeight) * PxPi * r * r; + + PxReal a = r*r*r * (8.0f / 15.0f) + h*r*r * (3.0f / 2.0f) + h*h*r * (4.0f / 3.0f) + h*h*h * (2.0f / 3.0f); + PxReal b = r*r*r * (8.0f / 15.0f) + h*r*r; + inertiaTensor = PxMat33::createDiagonal(PxVec3(b, a, a) * PxPi * r * r); + centerOfMass = PxVec3(0.0f); + } + break; + + case PxGeometryType::eCONVEXMESH: + { + const PxConvexMeshGeometry& c = static_cast(geometry); + PxVec3 unscaledCoM; + PxMat33 unscaledInertiaTensorNonCOM; // inertia tensor of convex mesh in mesh local space + PxMat33 unscaledInertiaTensorCOM; + PxReal unscaledMass; + c.convexMesh->getMassInformation(unscaledMass, unscaledInertiaTensorNonCOM, unscaledCoM); + + // inertia tensor relative to center of mass + unscaledInertiaTensorCOM[0][0] = unscaledInertiaTensorNonCOM[0][0] - unscaledMass*PxReal((unscaledCoM.y*unscaledCoM.y+unscaledCoM.z*unscaledCoM.z)); + unscaledInertiaTensorCOM[1][1] = unscaledInertiaTensorNonCOM[1][1] - unscaledMass*PxReal((unscaledCoM.z*unscaledCoM.z+unscaledCoM.x*unscaledCoM.x)); + unscaledInertiaTensorCOM[2][2] = unscaledInertiaTensorNonCOM[2][2] - unscaledMass*PxReal((unscaledCoM.x*unscaledCoM.x+unscaledCoM.y*unscaledCoM.y)); + unscaledInertiaTensorCOM[0][1] = unscaledInertiaTensorCOM[1][0] = (unscaledInertiaTensorNonCOM[0][1] + unscaledMass*PxReal(unscaledCoM.x*unscaledCoM.y)); + unscaledInertiaTensorCOM[1][2] = unscaledInertiaTensorCOM[2][1] = (unscaledInertiaTensorNonCOM[1][2] + unscaledMass*PxReal(unscaledCoM.y*unscaledCoM.z)); + unscaledInertiaTensorCOM[0][2] = unscaledInertiaTensorCOM[2][0] = (unscaledInertiaTensorNonCOM[0][2] + unscaledMass*PxReal(unscaledCoM.z*unscaledCoM.x)); + + const PxMeshScale& s = c.scale; + mass = unscaledMass * s.scale.x * s.scale.y * s.scale.z; + centerOfMass = s.rotation.rotate(s.scale.multiply(s.rotation.rotateInv(unscaledCoM))); + inertiaTensor = scaleInertia(unscaledInertiaTensorCOM, s.rotation, s.scale); + } + break; + + case PxGeometryType::eHEIGHTFIELD: + case PxGeometryType::ePLANE: + case PxGeometryType::eTRIANGLEMESH: + case PxGeometryType::eINVALID: + case PxGeometryType::eGEOMETRY_COUNT: + { + *this = PxMassProperties(); + } + break; + } + + PX_ASSERT(inertiaTensor.column0.isFinite() && inertiaTensor.column1.isFinite() && inertiaTensor.column2.isFinite()); + PX_ASSERT(centerOfMass.isFinite()); + PX_ASSERT(PxIsFinite(mass)); + } + + /** + \brief Scale mass properties. + + \param[in] scale The linear scaling factor to apply to the mass properties. + \return The scaled mass properties. + */ + PX_FORCE_INLINE PxMassProperties operator*(const PxReal scale) const + { + PX_ASSERT(PxIsFinite(scale)); + + return PxMassProperties(mass * scale, inertiaTensor * scale, centerOfMass); + } + + /** + \brief Translate the center of mass by a given vector and adjust the inertia tensor accordingly. + + \param[in] t The translation vector for the center of mass. + */ + PX_FORCE_INLINE void translate(const PxVec3& t) + { + PX_ASSERT(t.isFinite()); + + inertiaTensor = translateInertia(inertiaTensor, mass, t); + centerOfMass += t; + + PX_ASSERT(inertiaTensor.column0.isFinite() && inertiaTensor.column1.isFinite() && inertiaTensor.column2.isFinite()); + PX_ASSERT(centerOfMass.isFinite()); + } + + /** + \brief Get the entries of the diagonalized inertia tensor and the corresponding reference rotation. + + \param[in] inertia The inertia tensor to diagonalize. + \param[out] massFrame The frame the diagonalized tensor refers to. + \return The entries of the diagonalized inertia tensor. + */ + PX_FORCE_INLINE static PxVec3 getMassSpaceInertia(const PxMat33& inertia, PxQuat& massFrame) + { + PX_ASSERT(inertia.column0.isFinite() && inertia.column1.isFinite() && inertia.column2.isFinite()); + + PxVec3 diagT = PxDiagonalize(inertia, massFrame); + PX_ASSERT(diagT.isFinite()); + PX_ASSERT(massFrame.isFinite()); + return diagT; + } + + /** + \brief Translate an inertia tensor using the parallel axis theorem + + \param[in] inertia The inertia tensor to translate. + \param[in] mass The mass of the object. + \param[in] t The relative frame to translate the inertia tensor to. + \return The translated inertia tensor. + */ + PX_FORCE_INLINE static PxMat33 translateInertia(const PxMat33& inertia, const PxReal mass, const PxVec3& t) + { + PX_ASSERT(inertia.column0.isFinite() && inertia.column1.isFinite() && inertia.column2.isFinite()); + PX_ASSERT(PxIsFinite(mass)); + PX_ASSERT(t.isFinite()); + + PxMat33 s( PxVec3(0,t.z,-t.y), + PxVec3(-t.z,0,t.x), + PxVec3(t.y,-t.x,0) ); + + PxMat33 translatedIT = s.getTranspose() * s * mass + inertia; + PX_ASSERT(translatedIT.column0.isFinite() && translatedIT.column1.isFinite() && translatedIT.column2.isFinite()); + return translatedIT; + } + + /** + \brief Rotate an inertia tensor around the center of mass + + \param[in] inertia The inertia tensor to rotate. + \param[in] q The rotation to apply to the inertia tensor. + \return The rotated inertia tensor. + */ + PX_FORCE_INLINE static PxMat33 rotateInertia(const PxMat33& inertia, const PxQuat& q) + { + PX_ASSERT(inertia.column0.isFinite() && inertia.column1.isFinite() && inertia.column2.isFinite()); + PX_ASSERT(q.isUnit()); + + PxMat33 m(q); + PxMat33 rotatedIT = m * inertia * m.getTranspose(); + PX_ASSERT(rotatedIT.column0.isFinite() && rotatedIT.column1.isFinite() && rotatedIT.column2.isFinite()); + return rotatedIT; + } + + /** + \brief Non-uniform scaling of the inertia tensor + + \param[in] inertia The inertia tensor to scale. + \param[in] scaleRotation The frame of the provided scaling factors. + \param[in] scale The scaling factor for each axis (relative to the frame specified in scaleRotation). + \return The scaled inertia tensor. + */ + static PxMat33 scaleInertia(const PxMat33& inertia, const PxQuat& scaleRotation, const PxVec3& scale) + { + PX_ASSERT(inertia.column0.isFinite() && inertia.column1.isFinite() && inertia.column2.isFinite()); + PX_ASSERT(scaleRotation.isUnit()); + PX_ASSERT(scale.isFinite()); + + PxMat33 localInertiaT = rotateInertia(inertia, scaleRotation); // rotate inertia into scaling frame + PxVec3 diagonal(localInertiaT[0][0], localInertiaT[1][1], localInertiaT[2][2]); + + PxVec3 xyz2 = PxVec3(diagonal.dot(PxVec3(0.5f))) - diagonal; // original x^2, y^2, z^2 + PxVec3 scaledxyz2 = xyz2.multiply(scale).multiply(scale); + + PxReal xx = scaledxyz2.y + scaledxyz2.z, + yy = scaledxyz2.z + scaledxyz2.x, + zz = scaledxyz2.x + scaledxyz2.y; + + PxReal xy = localInertiaT[0][1] * scale.x * scale.y, + xz = localInertiaT[0][2] * scale.x * scale.z, + yz = localInertiaT[1][2] * scale.y * scale.z; + + PxMat33 scaledInertia( PxVec3(xx, xy, xz), + PxVec3(xy, yy, yz), + PxVec3(xz, yz, zz)); + + PxMat33 scaledIT = rotateInertia(scaledInertia * (scale.x * scale.y * scale.z), scaleRotation.getConjugate()); + PX_ASSERT(scaledIT.column0.isFinite() && scaledIT.column1.isFinite() && scaledIT.column2.isFinite()); + return scaledIT; + } + + /** + \brief Sum up individual mass properties. + + \param[in] props Array of mass properties to sum up. + \param[in] transforms Reference transforms for each mass properties entry. + \param[in] count The number of mass properties to sum up. + \return The summed up mass properties. + */ + static PxMassProperties sum(const PxMassProperties* props, const PxTransform* transforms, const PxU32 count) + { + PxReal combinedMass = 0.0f; + PxVec3 combinedCoM(0.0f); + PxMat33 combinedInertiaT = PxMat33(PxZero); + + for(PxU32 i = 0; i < count; i++) + { + PX_ASSERT(props[i].inertiaTensor.column0.isFinite() && props[i].inertiaTensor.column1.isFinite() && props[i].inertiaTensor.column2.isFinite()); + PX_ASSERT(props[i].centerOfMass.isFinite()); + PX_ASSERT(PxIsFinite(props[i].mass)); + + combinedMass += props[i].mass; + const PxVec3 comTm = transforms[i].transform(props[i].centerOfMass); + combinedCoM += comTm * props[i].mass; + } + + if(combinedMass > 0.f) + combinedCoM /= combinedMass; + + for(PxU32 i = 0; i < count; i++) + { + const PxVec3 comTm = transforms[i].transform(props[i].centerOfMass); + combinedInertiaT += translateInertia(rotateInertia(props[i].inertiaTensor, transforms[i].q), props[i].mass, combinedCoM - comTm); + } + + PX_ASSERT(combinedInertiaT.column0.isFinite() && combinedInertiaT.column1.isFinite() && combinedInertiaT.column2.isFinite()); + PX_ASSERT(combinedCoM.isFinite()); + PX_ASSERT(PxIsFinite(combinedMass)); + + return PxMassProperties(combinedMass, combinedInertiaT, combinedCoM); + } + + + PxMat33 inertiaTensor; //!< The inertia tensor of the object. + PxVec3 centerOfMass; //!< The center of mass of the object. + PxReal mass; //!< The mass of the object. +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/extensions/PxPrismaticJoint.h b/sources/PhysX/PhysX/include/extensions/PxPrismaticJoint.h new file mode 100644 index 00000000..e59207a0 --- /dev/null +++ b/sources/PhysX/PhysX/include/extensions/PxPrismaticJoint.h @@ -0,0 +1,236 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_PRISMATICJOINT_H +#define PX_PRISMATICJOINT_H +/** \addtogroup extensions + @{ +*/ + +#include "extensions/PxJoint.h" +#include "extensions/PxJointLimit.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxPrismaticJoint; + +/** +\brief Create a prismatic joint. + + \param[in] physics The physics SDK + \param[in] actor0 An actor to which the joint is attached. NULL may be used to attach the joint to a specific point in the world frame + \param[in] localFrame0 The position and orientation of the joint relative to actor0 + \param[in] actor1 An actor to which the joint is attached. NULL may be used to attach the joint to a specific point in the world frame + \param[in] localFrame1 The position and orientation of the joint relative to actor1 + +@see PxPrismaticJoint +*/ +PxPrismaticJoint* PxPrismaticJointCreate(PxPhysics& physics, PxRigidActor* actor0, const PxTransform& localFrame0, PxRigidActor* actor1, const PxTransform& localFrame1); + + +/** +\brief Flags specific to the prismatic joint. + +@see PxPrismaticJoint +*/ +struct PxPrismaticJointFlag +{ + enum Enum + { + eLIMIT_ENABLED = 1<<1 + }; +}; + +typedef PxFlags PxPrismaticJointFlags; +PX_FLAGS_OPERATORS(PxPrismaticJointFlag::Enum, PxU16) + +/** + \brief A prismatic joint permits relative translational movement between two bodies along + an axis, but no relative rotational movement. + + the axis on each body is defined as the line containing the origin of the joint frame and + extending along the x-axis of that frame + + \image html prismJoint.png + + @see PxPrismaticJointCreate() PxJoint +*/ +class PxPrismaticJoint : public PxJoint +{ +public: + + /** + \brief returns the displacement of the joint along its axis. + */ + virtual PxReal getPosition() const = 0; + + /** + \brief returns the velocity of the joint along its axis + */ + virtual PxReal getVelocity() const = 0; + + /** + \brief sets the joint limit parameters. + + The limit range is [-PX_MAX_F32, PX_MAX_F32], but note that the width of the limit (upper-lower) must also be + a valid float. + + @see PxJointLinearLimitPair getLimit() + */ + virtual void setLimit(const PxJointLinearLimitPair&) = 0; + + /** + \brief gets the joint limit parameters. + + @see PxJointLinearLimit getLimit() + */ + virtual PxJointLinearLimitPair getLimit() const = 0; + + /** + \brief Set the flags specific to the Prismatic Joint. + + Default PxPrismaticJointFlags(0) + + \param[in] flags The joint flags. + + @see PxPrismaticJointFlag setFlag() getFlags() + */ + virtual void setPrismaticJointFlags(PxPrismaticJointFlags flags) = 0; + + /** + \brief Set a single flag specific to a Prismatic Joint to true or false. + + \param[in] flag The flag to set or clear. + \param[in] value The value to which to set the flag + + @see PxPrismaticJointFlag, getFlags() setFlags() + */ + virtual void setPrismaticJointFlag(PxPrismaticJointFlag::Enum flag, bool value) = 0; + + /** + \brief Get the flags specific to the Prismatic Joint. + + \return the joint flags + + @see PxPrismaticJoint::flags, PxPrismaticJointFlag setFlag() setFlags() + */ + virtual PxPrismaticJointFlags getPrismaticJointFlags() const = 0; + + /** + \brief Set the linear tolerance threshold for projection. + + If the joint separates by more than this distance along its locked degrees of freedom, the solver + will move the bodies to close the distance. + + Setting a very small tolerance may result in simulation jitter or other artifacts. + + Sometimes it is not possible to project (for example when the joints form a cycle). + + This value must be nonnegative. + + Range: [0, PX_MAX_F32)
+ Default: 1e10f + + \param[in] tolerance the linear tolerance threshold + + @see getProjectionLinearTolerance() + */ + virtual void setProjectionLinearTolerance(PxReal tolerance) = 0; + + /** + \brief Get the linear tolerance threshold for projection. + + \return the linear tolerance threshold in radians + + @see setProjectionLinearTolerance() + */ + virtual PxReal getProjectionLinearTolerance() const = 0; + + /** + \brief Set the angular tolerance threshold for projection. Projection is enabled if PxConstraintFlag::ePROJECTION + is set for the joint. + + If the joint separates by more than this distance along its locked degrees of freedom, the solver + will move the bodies to close the distance. + + Setting a very small tolerance may result in simulation jitter or other artifacts. + + Sometimes it is not possible to project (for example when the joints form a cycle). + + Range: [0, PX_MAX_F32)
+ Default: Pi + + \param[in] tolerance the linear tolerance threshold + + @see getProjectionLinearTolerance() PxJoint::setConstraintFlags() + */ + virtual void setProjectionAngularTolerance(PxReal tolerance) = 0; + + /** + \brief Get the angular tolerance threshold for projection. + + @see getProjectionAngularTolerance() + */ + virtual PxReal getProjectionAngularTolerance() const = 0; + + /** + \brief Returns string name of PxPrismaticJoint, used for serialization + */ + virtual const char* getConcreteTypeName() const { return "PxPrismaticJoint"; } + +protected: + //serialization + + /** + \brief Constructor + */ + PX_INLINE PxPrismaticJoint(PxType concreteType, PxBaseFlags baseFlags) : PxJoint(concreteType, baseFlags) {} + + /** + \brief Deserialization constructor + */ + PX_INLINE PxPrismaticJoint(PxBaseFlags baseFlags) : PxJoint(baseFlags) {} + + /** + \brief Returns whether a given type name matches with the type of this instance + */ + virtual bool isKindOf(const char* name) const { return !::strcmp("PxPrismaticJoint", name) || PxJoint::isKindOf(name); } + + //~serialization +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/extensions/PxRaycastCCD.h b/sources/PhysX/PhysX/include/extensions/PxRaycastCCD.h new file mode 100644 index 00000000..92717819 --- /dev/null +++ b/sources/PhysX/PhysX/include/extensions/PxRaycastCCD.h @@ -0,0 +1,100 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_RAYCAST_CCD_H +#define PX_RAYCAST_CCD_H +/** \addtogroup extensions +@{ +*/ + +#include "common/PxPhysXCommonConfig.h" +#include "foundation/PxVec3.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + + class PxScene; + class PxShape; + class PxRigidDynamic; + class RaycastCCDManagerInternal; + + /** + \brief Raycast-CCD manager. + + Raycast-CCD is a simple and potentially cheaper alternative to the SDK's built-in continuous collision detection algorithm. + + This implementation has some limitations: + - it is only implemented for PxRigidDynamic objects (not for PxArticulationLink) + - it is only implemented for simple actors with 1 shape (not for "compounds") + + Also, since it is raycast-based, the solution is not perfect. In particular: + - small dynamic objects can still go through the static world if the ray goes through a crack between edges, or a small + hole in the world (like the keyhole from a door). + - dynamic-vs-dynamic CCD is very approximate. It only works well for fast-moving dynamic objects colliding against + slow-moving dynamic objects. + + Finally, since it is using the SDK's scene queries under the hood, it only works provided the simulation shapes also have + scene-query shapes associated with them. That is, if the objects in the scene only use PxShapeFlag::eSIMULATION_SHAPE + (and no PxShapeFlag::eSCENE_QUERY_SHAPE), then the raycast-CCD system will not work. + */ + class RaycastCCDManager + { + public: + RaycastCCDManager(PxScene* scene); + ~RaycastCCDManager(); + + /** + \brief Register dynamic object for raycast CCD. + + \param[in] actor object's actor + \param[in] shape object's shape + + \return True if success + */ + bool registerRaycastCCDObject(PxRigidDynamic* actor, PxShape* shape); + + /** + \brief Perform raycast CCD. Call this after your simulate/fetchResults calls. + + \param[in] doDynamicDynamicCCD True to enable dynamic-vs-dynamic CCD (more expensive, not always needed) + */ + void doRaycastCCD(bool doDynamicDynamicCCD); + + private: + RaycastCCDManagerInternal* mImpl; + }; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/extensions/PxRepXSerializer.h b/sources/PhysX/PhysX/include/extensions/PxRepXSerializer.h new file mode 100644 index 00000000..f75320b6 --- /dev/null +++ b/sources/PhysX/PhysX/include/extensions/PxRepXSerializer.h @@ -0,0 +1,148 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. +#ifndef PX_REPX_SERIALIZER_H +#define PX_REPX_SERIALIZER_H +/** \addtogroup Serializers + @{ +*/ + +#include "common/PxBase.h" +#include "extensions/PxRepXSimpleType.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + + class XmlMemoryAllocator; + class XmlWriter; + class XmlReader; + class MemoryBuffer; + + /** + \brief Serializer interface for RepX (Xml) serialization. + + In order to serialize a class to RepX both a PxSerializer and + a PxRepXSerializer implementation are needed. + + A repx Serializer provides the ability to capture a live + object to a descriptor or static state and the ability to + write that state out to a file. Objects allocated + by the Serializer using the allocator are freed when the + collection itself is freed. + SnRepXCoreSerializers.cpp implements a set of Serializers + for the core PhysX types. + + \note Implementing a PxRepXSerializer is currently not practical without including the internal PhysXExtension header "SnRepXSerializerImpl.h". + + @see PxSerializer, PX_NEW_REPX_SERIALIZER, PxSerializationRegistry::registerRepXSerializer + */ + class PxRepXSerializer + { + protected: + virtual ~PxRepXSerializer(){} + public: + + /** + \brief The type this Serializer is meant to operate on. + @see PxRepXObject::typeName + */ + virtual const char* getTypeName() = 0; + + /** + \brief Convert from a RepX object to a key-value pair hierarchy + + \param[in] inLiveObject The object to convert to the passed in descriptor. + \param[in] inCollection The collection to use to find ids of references of this object. + \param[in] inWriter Interface to write data to. + \param[in] inTempBuffer used to for temporary allocations. + \param[in] inArgs The arguments used in create resources and objects. + */ + virtual void objectToFile( const PxRepXObject& inLiveObject, PxCollection* inCollection, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs& inArgs ) = 0; + + /** + \brief Convert from a descriptor to a live object. Must be an object of this Serializer type. + + \param[in] inReader The inverse of the writer, a key-value pair database. + \param[in] inAllocator An allocator to use for temporary allocations. These will be freed after instantiation completes. + \param[in] inArgs The arguments used in create resources and objects. + \param[in] inCollection The collection used to find references. + + \return The new live object. It can be an invalid object if the instantiation cannot take place. + */ + virtual PxRepXObject fileToObject( XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* inCollection ) = 0; + + }; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** +\brief Inline helper template function to create PxRepXObject from TDataType type supporting PxTypeInfo::name. +*/ +template +PX_INLINE physx::PxRepXObject PxCreateRepXObject(const TDataType* inType, const physx::PxSerialObjectId inId) +{ + return physx::PxRepXObject(physx::PxTypeInfo::name(), inType, inId); +} + +/** +\brief Inline helper function to create PxRepXObject from a PxBase instance. +*/ +PX_INLINE physx::PxRepXObject PxCreateRepXObject(const physx::PxBase* inType, const physx::PxSerialObjectId inId) +{ + PX_ASSERT(inType); + return physx::PxRepXObject(inType->getConcreteTypeName(), inType, inId); +} + +/** +\brief Inline helper template function to create PxRepXObject form TDataType type using inType pointer as a PxSerialObjectId id. +*/ +template +PX_INLINE physx::PxRepXObject PxCreateRepXObject(const TDataType* inType) +{ + return PxCreateRepXObject(inType, static_cast(reinterpret_cast(inType))); +} + +/** +\brief Preprocessor macro for RepX serializer creation. +*/ +#define PX_NEW_REPX_SERIALIZER(T) \ + *PX_PLACEMENT_NEW(PxGetFoundation().getAllocatorCallback().allocate(sizeof(T), "PxRepXSerializer", __FILE__, __LINE__ ), T)(PxGetFoundation().getAllocatorCallback()) + +/** +\brief Preprocessor Macro to simplify RepX serializer delete. +*/ +#define PX_DELETE_REPX_SERIALIZER(x) \ + { PxRepXSerializer* s = x; if (s) { PxGetFoundation().getAllocatorCallback().deallocate(s); } } + + +/** @} */ +#endif // PX_REPX_SERIALIZER_H diff --git a/sources/PhysX/PhysX/include/extensions/PxRepXSimpleType.h b/sources/PhysX/PhysX/include/extensions/PxRepXSimpleType.h new file mode 100644 index 00000000..a49ad233 --- /dev/null +++ b/sources/PhysX/PhysX/include/extensions/PxRepXSimpleType.h @@ -0,0 +1,106 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + + +#ifndef PX_REPX_SIMPLE_TYPE_H +#define PX_REPX_SIMPLE_TYPE_H + +/** \addtogroup extensions + @{ +*/ + +#include "foundation/PxSimpleTypes.h" +#include "cooking/PxCooking.h" +#include "common/PxStringTable.h" +#include "common/PxSerialFramework.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + + /** + \brief Helper class containing the mapping of id to object, and type name. + */ + struct PxRepXObject + { + /** + \brief Identifies the extension meant to handle this object. + @see PxTypeInfo, PX_DEFINE_TYPEINFO, PxRepXSerializer + */ + const char* typeName; + + /** + \brief Pointer to the serializable this was created from + */ + const void* serializable; + + /** + \brief Id given to this object at some point + */ + PxSerialObjectId id; + PxRepXObject( const char* inTypeName = "", const void* inSerializable = NULL, const PxSerialObjectId inId = 0 ) + : typeName( inTypeName ) + , serializable( inSerializable ) + , id( inId ) + { + } + bool isValid() const { return serializable != NULL; } + }; + + /** + \brief Arguments required to instantiate a serializable object from RepX. + + Extra arguments can be added to the object map under special ids. + + @see PxRepXSerializer::objectToFile, PxRepXSerializer::fileToObject + */ + struct PxRepXInstantiationArgs + { + PxPhysics& physics; + PxCooking* cooker; + PxStringTable* stringTable; + PxRepXInstantiationArgs( PxPhysics& inPhysics, PxCooking* inCooking = NULL , PxStringTable* inStringTable = NULL ) + : physics( inPhysics ) + , cooker( inCooking ) + , stringTable( inStringTable ) + { + } + + PxRepXInstantiationArgs& operator=(const PxRepXInstantiationArgs&); + }; + + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/extensions/PxRevoluteJoint.h b/sources/PhysX/PhysX/include/extensions/PxRevoluteJoint.h new file mode 100644 index 00000000..8d82c8cb --- /dev/null +++ b/sources/PhysX/PhysX/include/extensions/PxRevoluteJoint.h @@ -0,0 +1,332 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_REVOLUTEJOINT_H +#define PX_REVOLUTEJOINT_H +/** \addtogroup extensions + @{ +*/ + +#include "extensions/PxJoint.h" +#include "extensions/PxJointLimit.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxRevoluteJoint; + +/** +\brief Create a revolute joint. + + \param[in] physics The physics SDK + \param[in] actor0 An actor to which the joint is attached. NULL may be used to attach the joint to a specific point in the world frame + \param[in] localFrame0 The position and orientation of the joint relative to actor0 + \param[in] actor1 An actor to which the joint is attached. NULL may be used to attach the joint to a specific point in the world frame + \param[in] localFrame1 The position and orientation of the joint relative to actor1 + +@see PxRevoluteJoint +*/ +PxRevoluteJoint* PxRevoluteJointCreate(PxPhysics& physics, PxRigidActor* actor0, const PxTransform& localFrame0, PxRigidActor* actor1, const PxTransform& localFrame1); + +/** +\brief Flags specific to the Revolute Joint. + +@see PxRevoluteJoint +*/ +struct PxRevoluteJointFlag +{ + enum Enum + { + eLIMIT_ENABLED = 1<<0, //!< enable the limit + eDRIVE_ENABLED = 1<<1, //!< enable the drive + eDRIVE_FREESPIN = 1<<2 //!< if the existing velocity is beyond the drive velocity, do not add force + }; +}; + +typedef PxFlags PxRevoluteJointFlags; +PX_FLAGS_OPERATORS(PxRevoluteJointFlag::Enum, PxU16) + +/** + +\brief A joint which behaves in a similar way to a hinge or axle. + + A hinge joint removes all but a single rotational degree of freedom from two objects. + The axis along which the two bodies may rotate is specified with a point and a direction + vector. + + The position of the hinge on each body is specified by the origin of the body's joint frame. + The axis of the hinge is specified as the direction of the x-axis in the body's joint frame. + + \image html revoluteJoint.png + + A revolute joint can be given a motor, so that it can apply a force to rotate the attached actors. + It may also be given a limit, to restrict the revolute motion to within a certain range. In + addition, the bodies may be projected together if the distance or angle between them exceeds + a given threshold. + + Projection, drive and limits are activated by setting the appropriate flags on the joint. + + @see PxRevoluteJointCreate() PxJoint +*/ +class PxRevoluteJoint : public PxJoint +{ +public: + + /** + \brief return the angle of the joint, in the range (-2*Pi, 2*Pi] + */ + virtual PxReal getAngle() const = 0; + + /** + \brief return the velocity of the joint + */ + virtual PxReal getVelocity() const = 0; + + /** + \brief set the joint limit parameters. + + The limit is activated using the flag PxRevoluteJointFlag::eLIMIT_ENABLED + + The limit angle range is (-2*Pi, 2*Pi). + + \param[in] limits The joint limit parameters. + + @see PxJointAngularLimitPair getLimit() + */ + virtual void setLimit(const PxJointAngularLimitPair& limits) = 0; + + /** + \brief get the joint limit parameters. + + \return the joint limit parameters + + @see PxJointAngularLimitPair setLimit() + */ + virtual PxJointAngularLimitPair getLimit() const = 0; + + /** + \brief set the target velocity for the drive model. + + The motor will only be able to reach this velocity if the maxForce is sufficiently large. + If the joint is spinning faster than this velocity, the motor will actually try to brake + (see PxRevoluteJointFlag::eDRIVE_FREESPIN.) + + If you set this to infinity then the motor will keep speeding up, unless there is some sort + of resistance on the attached bodies. The sign of this variable determines the rotation direction, + with positive values going the same way as positive joint angles. + + \param[in] velocity the drive target velocity + \param[in] autowake Whether to wake the joint rigids up if it is asleep. + + Range: [0, PX_MAX_F32)
+ Default: 0.0 + + @see PxRevoluteFlags::eDRIVE_FREESPIN + */ + virtual void setDriveVelocity(PxReal velocity, bool autowake = true) = 0; + + /** + \brief gets the target velocity for the drive model. + + \return the drive target velocity + + @see setDriveVelocity() + */ + virtual PxReal getDriveVelocity() const = 0; + + /** + \brief sets the maximum torque the drive can exert. + + Setting this to a very large value if velTarget is also very large may cause unexpected results. + + The value set here may be used either as an impulse limit or a force limit, depending on the flag PxConstraintFlag::eDRIVE_LIMITS_ARE_FORCES + + Range: [0, PX_MAX_F32)
+ Default: PX_MAX_F32 + + @see setDriveVelocity() + */ + virtual void setDriveForceLimit(PxReal limit) = 0; + + /** + \brief gets the maximum torque the drive can exert. + + \return the torque limit + + @see setDriveVelocity() + */ + virtual PxReal getDriveForceLimit() const = 0; + + /** + \brief sets the gear ratio for the drive. + + When setting up the drive constraint, the velocity of the first actor is scaled by this value, and its response to drive torque is scaled down. + So if the drive target velocity is zero, the second actor will be driven to the velocity of the first scaled by the gear ratio + + Range: [0, PX_MAX_F32)
+ Default: 1.0 + + \param[in] ratio the drive gear ratio + + @see getDriveGearRatio() + */ + virtual void setDriveGearRatio(PxReal ratio) = 0; + + /** + \brief gets the gear ratio. + + \return the drive gear ratio + + @see setDriveGearRatio() + */ + virtual PxReal getDriveGearRatio() const = 0; + + /** + \brief sets the flags specific to the Revolute Joint. + + Default PxRevoluteJointFlags(0) + + \param[in] flags The joint flags. + + @see PxRevoluteJointFlag setFlag() getFlags() + */ + virtual void setRevoluteJointFlags(PxRevoluteJointFlags flags) = 0; + + /** + \brief sets a single flag specific to a Revolute Joint. + + \param[in] flag The flag to set or clear. + \param[in] value the value to which to set the flag + + @see PxRevoluteJointFlag, getFlags() setFlags() + */ + virtual void setRevoluteJointFlag(PxRevoluteJointFlag::Enum flag, bool value) = 0; + + /** + \brief gets the flags specific to the Revolute Joint. + + \return the joint flags + + @see PxRevoluteJoint::flags, PxRevoluteJointFlag setFlag() setFlags() + */ + virtual PxRevoluteJointFlags getRevoluteJointFlags() const = 0; + + /** + \brief Set the linear tolerance threshold for projection. Projection is enabled if PxConstraintFlag::ePROJECTION + is set for the joint. + + If the joint separates by more than this distance along its locked degrees of freedom, the solver + will move the bodies to close the distance. + + Setting a very small tolerance may result in simulation jitter or other artifacts. + + Sometimes it is not possible to project (for example when the joints form a cycle). + + Range: [0, PX_MAX_F32)
+ Default: 1e10f + + \param[in] tolerance the linear tolerance threshold + + @see getProjectionLinearTolerance() PxJoint::setConstraintFlags() PxConstraintFlag::ePROJECTION + */ + virtual void setProjectionLinearTolerance(PxReal tolerance) = 0; + + /** + \brief Get the linear tolerance threshold for projection. + + \return the linear tolerance threshold + + @see setProjectionLinearTolerance() + */ + virtual PxReal getProjectionLinearTolerance() const = 0; + + /** + \brief Set the angular tolerance threshold for projection. Projection is enabled if + PxConstraintFlag::ePROJECTION is set for the joint. + + If the joint deviates by more than this angle around its locked angular degrees of freedom, + the solver will move the bodies to close the angle. + + Setting a very small tolerance may result in simulation jitter or other artifacts. + + Sometimes it is not possible to project (for example when the joints form a cycle). + + Range: [0,Pi]
+ Default: Pi + + \param[in] tolerance the angular tolerance threshold in radians + + @see getProjectionAngularTolerance() PxJoint::setConstraintFlag() PxConstraintFlag::ePROJECTION + */ + virtual void setProjectionAngularTolerance(PxReal tolerance) = 0; + + /** + \brief gets the angular tolerance threshold for projection. + + \return the angular tolerance threshold in radians + + @see setProjectionAngularTolerance() + */ + virtual PxReal getProjectionAngularTolerance() const = 0; + + /** + \brief Returns string name of PxRevoluteJoint, used for serialization + */ + virtual const char* getConcreteTypeName() const { return "PxRevoluteJoint"; } + +protected: + + //serialization + + /** + \brief Constructor + */ + PX_INLINE PxRevoluteJoint(PxType concreteType, PxBaseFlags baseFlags) : PxJoint(concreteType, baseFlags) {} + + /** + \brief Deserialization constructor + */ + PX_INLINE PxRevoluteJoint(PxBaseFlags baseFlags) : PxJoint(baseFlags) {} + + /** + \brief Returns whether a given type name matches with the type of this instance + */ + virtual bool isKindOf(const char* name) const { return !::strcmp("PxRevoluteJoint", name) || PxJoint::isKindOf(name); } + + //~serialization +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/extensions/PxRigidActorExt.h b/sources/PhysX/PhysX/include/extensions/PxRigidActorExt.h new file mode 100644 index 00000000..c7a3b7bf --- /dev/null +++ b/sources/PhysX/PhysX/include/extensions/PxRigidActorExt.h @@ -0,0 +1,155 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_EXTENSIONS_RIGIDACTOR_H +#define PX_PHYSICS_EXTENSIONS_RIGIDACTOR_H +/** \addtogroup extensions + @{ +*/ + +#include "PxPhysXConfig.h" +#include "PxPhysics.h" +#include "PxRigidActor.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief utility functions for use with PxRigidActor and subclasses + +@see PxRigidActor PxRigidStatic PxRigidBody PxRigidDynamic PxArticulationLink +*/ + +class PxRigidActorExt +{ +public: + + /** + \brief Creates a new shape with default properties and a list of materials and adds it to the list of shapes of this actor. + + This is equivalent to the following + + PxShape* shape(...) = PxGetPhysics().createShape(...); // reference count is 1 + actor->attachShape(shape); // increments reference count + shape->release(); // releases user reference, leaving reference count at 1 + + As a consequence, detachShape() will result in the release of the last reference, and the shape will be deleted. + + \note The default shape flags to be set are: eVISUALIZATION, eSIMULATION_SHAPE, eSCENE_QUERY_SHAPE (see #PxShapeFlag). + Triangle mesh, heightfield or plane geometry shapes configured as eSIMULATION_SHAPE are not supported for + non-kinematic PxRigidDynamic instances. + + \note Creating compounds with a very large number of shapes may adversely affect performance and stability. + + Sleeping: Does NOT wake the actor up automatically. + + \param[in] actor the actor to which to attach the shape + \param[in] geometry the geometry of the shape + \param[in] materials a pointer to an array of material pointers + \param[in] materialCount the count of materials + \param[in] shapeFlags optional PxShapeFlags + + \return The newly created shape. + + @see PxShape PxShape::release(), PxPhysics::createShape(), PxRigidActor::attachShape() + */ + + static PxShape* createExclusiveShape(PxRigidActor& actor, const PxGeometry& geometry, PxMaterial*const* materials, PxU16 materialCount, + PxShapeFlags shapeFlags = PxShapeFlag::eVISUALIZATION | PxShapeFlag::eSCENE_QUERY_SHAPE | PxShapeFlag::eSIMULATION_SHAPE) + { + PxShape* shape = PxGetPhysics().createShape(geometry, materials, materialCount, true, shapeFlags); + if(shape) + { + bool status = actor.attachShape(*shape); // attach can fail, if e.g. we try and attach a trimesh simulation shape to a dynamic actor + shape->release(); // if attach fails, we hold the only counted reference, and so this cleans up properly + if(!status) + shape = NULL; + } + return shape; + } + + /** + \brief Creates a new shape with default properties and a single material adds it to the list of shapes of this actor. + + This is equivalent to the following + + PxShape* shape(...) = PxGetPhysics().createShape(...); // reference count is 1 + actor->attachShape(shape); // increments reference count + shape->release(); // releases user reference, leaving reference count at 1 + + As a consequence, detachShape() will result in the release of the last reference, and the shape will be deleted. + + \note The default shape flags to be set are: eVISUALIZATION, eSIMULATION_SHAPE, eSCENE_QUERY_SHAPE (see #PxShapeFlag). + Triangle mesh, heightfield or plane geometry shapes configured as eSIMULATION_SHAPE are not supported for + non-kinematic PxRigidDynamic instances. + + \note Creating compounds with a very large number of shapes may adversely affect performance and stability. + + Sleeping: Does NOT wake the actor up automatically. + + \param[in] actor the actor to which to attach the shape + \param[in] geometry the geometry of the shape + \param[in] material the material for the shape + \param[in] shapeFlags optional PxShapeFlags + + \return The newly created shape. + + @see PxShape PxShape::release(), PxPhysics::createShape(), PxRigidActor::attachShape() + */ + + static PX_FORCE_INLINE PxShape* createExclusiveShape(PxRigidActor& actor, const PxGeometry& geometry, const PxMaterial& material, + PxShapeFlags shapeFlags = PxShapeFlag::eVISUALIZATION | PxShapeFlag::eSCENE_QUERY_SHAPE | PxShapeFlag::eSIMULATION_SHAPE) + { + PxMaterial* materialPtr = const_cast(&material); + return createExclusiveShape(actor, geometry, &materialPtr, 1, shapeFlags); + } + + + /** + \brief Gets a list of bounds based on shapes in rigid actor. This list can be used to cook/create + bounding volume hierarchy though PxCooking API. + + \param[in] actor The actor from which the bounds list is retrieved. + \param[out] numBounds Number of bounds in returned list. + + @see PxShape PxBVHStructure PxCooking::createBVHStructure PxCooking::cookBVHStructure + */ + static PxBounds3* getRigidActorShapeLocalBoundsList(const PxRigidActor& actor, PxU32& numBounds); + +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/extensions/PxRigidBodyExt.h b/sources/PhysX/PhysX/include/extensions/PxRigidBodyExt.h new file mode 100644 index 00000000..71228b3a --- /dev/null +++ b/sources/PhysX/PhysX/include/extensions/PxRigidBodyExt.h @@ -0,0 +1,460 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_EXTENSIONS_RIGIDBODY_H +#define PX_PHYSICS_EXTENSIONS_RIGIDBODY_H +/** \addtogroup extensions + @{ +*/ + +#include "PxPhysXConfig.h" +#include "PxRigidBody.h" +#include "PxQueryReport.h" +#include "PxQueryFiltering.h" +#include "extensions/PxMassProperties.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxScene; +struct PxQueryCache; +class PxShape; + +/** +\brief utility functions for use with PxRigidBody and subclasses + +@see PxRigidBody PxRigidDynamic PxArticulationLink +*/ + +class PxRigidBodyExt +{ +public: + /** + \brief Computation of mass properties for a rigid body actor + + To simulate a dynamic rigid actor, the SDK needs a mass and an inertia tensor. + + This method offers functionality to compute the necessary mass and inertia properties based on the shapes declared in + the PxRigidBody descriptor and some additionally specified parameters. For each shape, the shape geometry, + the shape positioning within the actor and the specified shape density are used to compute the body's mass and + inertia properties. + +
    +
  • Shapes without PxShapeFlag::eSIMULATION_SHAPE set are ignored unless includeNonSimShapes is true.
  • +
  • Shapes with plane, triangle mesh or heightfield geometry and PxShapeFlag::eSIMULATION_SHAPE set are not allowed for PxRigidBody collision.
  • +
+ + This method will set the mass, center of mass, and inertia tensor + + if no collision shapes are found, the inertia tensor is set to (1,1,1) and the mass to 1 + + if massLocalPose is non-NULL, the rigid body's center of mass parameter will be set + to the user provided value (massLocalPose) and the inertia tensor will be resolved at that point. + + \note If all shapes of the actor have the same density then the overloaded method updateMassAndInertia() with a single density parameter can be used instead. + + \param[in,out] body The rigid body. + \param[in] shapeDensities The per shape densities. There must be one entry for each shape which has the PxShapeFlag::eSIMULATION_SHAPE set (or for all shapes if includeNonSimShapes is set to true). Other shapes are ignored. The density values must be greater than 0. + \param[in] shapeDensityCount The number of provided density values. + \param[in] massLocalPose The center of mass relative to the actor frame. If set to null then (0,0,0) is assumed. + \param[in] includeNonSimShapes True if all kind of shapes (PxShapeFlag::eSCENE_QUERY_SHAPE, PxShapeFlag::eTRIGGER_SHAPE) should be taken into account. + \return Boolean. True on success else false. + + @see PxRigidBody::setMassLocalPose PxRigidBody::setMassSpaceInertiaTensor PxRigidBody::setMass + */ + static bool updateMassAndInertia(PxRigidBody& body, const PxReal* shapeDensities, PxU32 shapeDensityCount, const PxVec3* massLocalPose = NULL, bool includeNonSimShapes = false); + + + /** + \brief Computation of mass properties for a rigid body actor + + See previous method for details. + + \param[in,out] body The rigid body. + \param[in] density The density of the body. Used to compute the mass of the body. The density must be greater than 0. + \param[in] massLocalPose The center of mass relative to the actor frame. If set to null then (0,0,0) is assumed. + \param[in] includeNonSimShapes True if all kind of shapes (PxShapeFlag::eSCENE_QUERY_SHAPE, PxShapeFlag::eTRIGGER_SHAPE) should be taken into account. + \return Boolean. True on success else false. + + @see PxRigidBody::setMassLocalPose PxRigidBody::setMassSpaceInertiaTensor PxRigidBody::setMass + */ + static bool updateMassAndInertia(PxRigidBody& body, PxReal density, const PxVec3* massLocalPose = NULL, bool includeNonSimShapes = false); + + + /** + \brief Computation of mass properties for a rigid body actor + + This method sets the mass, inertia and center of mass of a rigid body. The mass is set to the sum of all user-supplied + shape mass values, and the inertia and center of mass are computed according to the rigid body's shapes and the per shape mass input values. + + If no collision shapes are found, the inertia tensor is set to (1,1,1) + + \note If a single mass value should be used for the actor as a whole then the overloaded method setMassAndUpdateInertia() with a single mass parameter can be used instead. + + @see updateMassAndInertia for more details. + + \param[in,out] body The rigid body for which to set the mass and centre of mass local pose properties. + \param[in] shapeMasses The per shape mass values. There must be one entry for each shape which has the PxShapeFlag::eSIMULATION_SHAPE set. Other shapes are ignored. The mass values must be greater than 0. + \param[in] shapeMassCount The number of provided mass values. + \param[in] massLocalPose The center of mass relative to the actor frame. If set to null then (0,0,0) is assumed. + \param[in] includeNonSimShapes True if all kind of shapes (PxShapeFlag::eSCENE_QUERY_SHAPE, PxShapeFlag::eTRIGGER_SHAPE) should be taken into account. + \return Boolean. True on success else false. + + @see PxRigidBody::setCMassLocalPose PxRigidBody::setMassSpaceInertiaTensor PxRigidBody::setMass + */ + static bool setMassAndUpdateInertia(PxRigidBody& body, const PxReal* shapeMasses, PxU32 shapeMassCount, const PxVec3* massLocalPose = NULL, bool includeNonSimShapes = false); + + + /** + \brief Computation of mass properties for a rigid body actor + + This method sets the mass, inertia and center of mass of a rigid body. The mass is set to the user-supplied + value, and the inertia and center of mass are computed according to the rigid body's shapes and the input mass. + + If no collision shapes are found, the inertia tensor is set to (1,1,1) + + @see updateMassAndInertia for more details. + + \param[in,out] body The rigid body for which to set the mass and centre of mass local pose properties. + \param[in] mass The mass of the body. Must be greater than 0. + \param[in] massLocalPose The center of mass relative to the actor frame. If set to null then (0,0,0) is assumed. + \param[in] includeNonSimShapes True if all kind of shapes (PxShapeFlag::eSCENE_QUERY_SHAPE, PxShapeFlag::eTRIGGER_SHAPE) should be taken into account. + \return Boolean. True on success else false. + + @see PxRigidBody::setCMassLocalPose PxRigidBody::setMassSpaceInertiaTensor PxRigidBody::setMass + */ + static bool setMassAndUpdateInertia(PxRigidBody& body, PxReal mass, const PxVec3* massLocalPose = NULL, bool includeNonSimShapes = false); + + + /** + \brief Compute the mass, inertia tensor and center of mass from a list of shapes. + + \param[in] shapes The shapes to compute the mass properties from. + \param[in] shapeCount The number of provided shapes. + \return The mass properties from the combined shapes. + + @see PxRigidBody::setCMassLocalPose PxRigidBody::setMassSpaceInertiaTensor PxRigidBody::setMass + */ + static PxMassProperties computeMassPropertiesFromShapes(const PxShape* const* shapes, PxU32 shapeCount); + + + /** + \brief Applies a force (or impulse) defined in the global coordinate frame, acting at a particular + point in global coordinates, to the actor. + + Note that if the force does not act along the center of mass of the actor, this + will also add the corresponding torque. Because forces are reset at the end of every timestep, + you can maintain a total external force on an object by calling this once every frame. + + \note if this call is used to apply a force or impulse to an articulation link, only the link is updated, not the entire + articulation + + ::PxForceMode determines if the force is to be conventional or impulsive. Only eFORCE and eIMPULSE are supported, as the + force required to produce a given velocity change or acceleration is underdetermined given only the desired change at a + given point. + + Sleeping: This call wakes the actor if it is sleeping and the wakeup parameter is true (default). + + \param[in] body The rigid body to apply the force to. + \param[in] force Force/impulse to add, defined in the global frame. Range: force vector + \param[in] pos Position in the global frame to add the force at. Range: position vector + \param[in] mode The mode to use when applying the force/impulse(see #PxForceMode). + \param[in] wakeup Specify if the call should wake up the actor. + + @see PxForceMode + @see addForceAtLocalPos() addLocalForceAtPos() addLocalForceAtLocalPos() + */ + static void addForceAtPos(PxRigidBody& body, const PxVec3& force, const PxVec3& pos, PxForceMode::Enum mode = PxForceMode::eFORCE, bool wakeup = true); + + /** + \brief Applies a force (or impulse) defined in the global coordinate frame, acting at a particular + point in local coordinates, to the actor. + + Note that if the force does not act along the center of mass of the actor, this + will also add the corresponding torque. Because forces are reset at the end of every timestep, you can maintain a + total external force on an object by calling this once every frame. + + \note if this call is used to apply a force or impulse to an articulation link, only the link is updated, not the entire + articulation + + ::PxForceMode determines if the force is to be conventional or impulsive. Only eFORCE and eIMPULSE are supported, as the + force required to produce a given velocity change or acceleration is underdetermined given only the desired change at a + given point. + + Sleeping: This call wakes the actor if it is sleeping and the wakeup parameter is true (default). + + \param[in] body The rigid body to apply the force to. + \param[in] force Force/impulse to add, defined in the global frame. Range: force vector + \param[in] pos Position in the local frame to add the force at. Range: position vector + \param[in] mode The mode to use when applying the force/impulse(see #PxForceMode). + \param[in] wakeup Specify if the call should wake up the actor. + + @see PxForceMode + @see addForceAtPos() addLocalForceAtPos() addLocalForceAtLocalPos() + */ + static void addForceAtLocalPos(PxRigidBody& body, const PxVec3& force, const PxVec3& pos, PxForceMode::Enum mode = PxForceMode::eFORCE, bool wakeup = true); + + /** + \brief Applies a force (or impulse) defined in the actor local coordinate frame, acting at a + particular point in global coordinates, to the actor. + + Note that if the force does not act along the center of mass of the actor, this + will also add the corresponding torque. Because forces are reset at the end of every timestep, you can maintain a + total external force on an object by calling this once every frame. + + \note if this call is used to apply a force or impulse to an articulation link, only the link is updated, not the entire + articulation + + ::PxForceMode determines if the force is to be conventional or impulsive. Only eFORCE and eIMPULSE are supported, as the + force required to produce a given velocity change or acceleration is underdetermined given only the desired change at a + given point. + + Sleeping: This call wakes the actor if it is sleeping and the wakeup parameter is true (default). + + \param[in] body The rigid body to apply the force to. + \param[in] force Force/impulse to add, defined in the local frame. Range: force vector + \param[in] pos Position in the global frame to add the force at. Range: position vector + \param[in] mode The mode to use when applying the force/impulse(see #PxForceMode). + \param[in] wakeup Specify if the call should wake up the actor. + + @see PxForceMode + @see addForceAtPos() addForceAtLocalPos() addLocalForceAtLocalPos() + */ + static void addLocalForceAtPos(PxRigidBody& body, const PxVec3& force, const PxVec3& pos, PxForceMode::Enum mode = PxForceMode::eFORCE, bool wakeup = true); + + /** + \brief Applies a force (or impulse) defined in the actor local coordinate frame, acting at a + particular point in local coordinates, to the actor. + + Note that if the force does not act along the center of mass of the actor, this + will also add the corresponding torque. Because forces are reset at the end of every timestep, you can maintain a + total external force on an object by calling this once every frame. + + \note if this call is used to apply a force or impulse to an articulation link, only the link is updated, not the entire + articulation + + ::PxForceMode determines if the force is to be conventional or impulsive. Only eFORCE and eIMPULSE are supported, as the + force required to produce a given velocity change or acceleration is underdetermined given only the desired change at a + given point. + + Sleeping: This call wakes the actor if it is sleeping and the wakeup parameter is true (default). + + \param[in] body The rigid body to apply the force to. + \param[in] force Force/impulse to add, defined in the local frame. Range: force vector + \param[in] pos Position in the local frame to add the force at. Range: position vector + \param[in] mode The mode to use when applying the force/impulse(see #PxForceMode). + \param[in] wakeup Specify if the call should wake up the actor. + + @see PxForceMode + @see addForceAtPos() addForceAtLocalPos() addLocalForceAtPos() + */ + static void addLocalForceAtLocalPos(PxRigidBody& body, const PxVec3& force, const PxVec3& pos, PxForceMode::Enum mode = PxForceMode::eFORCE, bool wakeup = true); + + /** + \brief Computes the velocity of a point given in world coordinates if it were attached to the + specified body and moving with it. + + \param[in] body The rigid body the point is attached to. + \param[in] pos Position we wish to determine the velocity for, defined in the global frame. Range: position vector + \return The velocity of point in the global frame. + + @see getLocalPointVelocity() + */ + static PxVec3 getVelocityAtPos(const PxRigidBody& body, const PxVec3& pos); + + /** + \brief Computes the velocity of a point given in local coordinates if it were attached to the + specified body and moving with it. + + \param[in] body The rigid body the point is attached to. + \param[in] pos Position we wish to determine the velocity for, defined in the local frame. Range: position vector + \return The velocity of point in the local frame. + + @see getLocalPointVelocity() + */ + static PxVec3 getLocalVelocityAtLocalPos(const PxRigidBody& body, const PxVec3& pos); + + /** + \brief Computes the velocity of a point (offset from the origin of the body) given in world coordinates if it were attached to the + specified body and moving with it. + + \param[in] body The rigid body the point is attached to. + \param[in] pos Position (offset from the origin of the body) we wish to determine the velocity for, defined in the global frame. Range: position vector + \return The velocity of point (offset from the origin of the body) in the global frame. + + @see getLocalPointVelocity() + */ + static PxVec3 getVelocityAtOffset(const PxRigidBody& body, const PxVec3& pos); + + + /** + \brief Performs a linear sweep through space with the body's geometry objects. + + \note Supported geometries are: box, sphere, capsule, convex. Other geometry types will be ignored. + \note If eTOUCH is returned from the filter callback, it will trigger an error and the hit will be discarded. + + The function sweeps all shapes attached to a given rigid body through space and reports the nearest + object in the scene which intersects any of of the shapes swept paths. + Information about the closest intersection is written to a #PxSweepHit structure. + + \param[in] body The rigid body to sweep. + \param[in] scene The scene object to process the query. + \param[in] unitDir Normalized direction of the sweep. + \param[in] distance Sweep distance. Needs to be larger than 0. + \param[in] outputFlags Specifies which properties should be written to the hit information. + \param[out] closestHit Closest hit result. + \param[out] shapeIndex Index of the body shape that caused the closest hit. + \param[in] filterData If any word in filterData.data is non-zero then filterData.data will be used for filtering, + otherwise shape->getQueryFilterData() will be used instead. + \param[in] filterCall Custom filtering logic (optional). Only used if the corresponding #PxQueryFlag flags are set. If NULL, all hits are assumed to be blocking. + \param[in] cache Cached hit shape (optional). Ray is tested against cached shape first then against the scene. + Note: Filtering is not executed for a cached shape if supplied; instead, if a hit is found, it is assumed to be a blocking hit. + \param[in] inflation This parameter creates a skin around the swept geometry which increases its extents for sweeping. The sweep will register a hit as soon as the skin touches a shape, and will return the corresponding distance and normal. + + \return True if a blocking hit was found. + + @see PxScene PxQueryFlags PxFilterData PxBatchQueryPreFilterShader PxBatchQueryPostFilterShader PxSweepHit + */ + static bool linearSweepSingle( + PxRigidBody& body, PxScene& scene, const PxVec3& unitDir, const PxReal distance, + PxHitFlags outputFlags, + PxSweepHit& closestHit, PxU32& shapeIndex, + const PxQueryFilterData& filterData = PxQueryFilterData(), + PxQueryFilterCallback* filterCall = NULL, + const PxQueryCache* cache = NULL, + const PxReal inflation=0.0f); + + /** + \brief Performs a linear sweep through space with the body's geometry objects, returning all overlaps. + + \note Supported geometries are: box, sphere, capsule, convex. Other geometry types will be ignored. + + This function sweeps all shapes attached to a given rigid body through space and reports all + objects in the scene that intersect any of the shapes' swept paths until there are no more objects to report + or a blocking hit is encountered. + + \param[in] body The rigid body to sweep. + \param[in] scene The scene object to process the query. + \param[in] unitDir Normalized direction of the sweep. + \param[in] distance Sweep distance. Needs to be larger than 0. + \param[in] outputFlags Specifies which properties should be written to the hit information. + \param[out] touchHitBuffer Raycast hit information buffer. If the buffer overflows, an arbitrary subset of touch hits + is returned (typically the query should be restarted with a larger buffer). + \param[out] touchHitShapeIndices After the query is completed, touchHitShapeIndices[i] will contain the body index that caused the hit stored in hitBuffer[i] + \param[in] touchHitBufferSize Size of both touch hit buffers in elements. + \param[out] block Closest blocking hit is returned via this reference. + \param[out] blockingShapeIndex Set to -1 if if a blocking hit was not found, otherwise set to closest blocking hit shape index. The touching hits are reported separately in hitBuffer. + \param[out] overflow Set to true if touchHitBuffer didn't have enough space for all results. Touch hits will be incomplete if overflow occurred. Possible solution is to restart the query with a larger buffer. + \param[in] filterData If any word in filterData.data is non-zero then filterData.data will be used for filtering, + otherwise shape->getQueryFilterData() will be used instead. + \param[in] filterCall Custom filtering logic (optional). Only used if the corresponding #PxQueryFlag flags are set. If NULL, all hits are assumed to be blocking. + \param[in] cache Cached hit shape (optional). Ray is tested against cached shape first then against the scene. + Note: Filtering is not executed for a cached shape if supplied; instead, if a hit is found, it is assumed to be a blocking hit. + \param[in] inflation This parameter creates a skin around the swept geometry which increases its extents for sweeping. The sweep will register a hit as soon as the skin touches a shape, and will return the corresponding distance and normal. + + \return the number of touching hits. If overflow is set to true, the results are incomplete. In case of overflow there are also no guarantees that all touching hits returned are closer than the blocking hit. + + @see PxScene PxQueryFlags PxFilterData PxBatchQueryPreFilterShader PxBatchQueryPostFilterShader PxSweepHit + */ + static PxU32 linearSweepMultiple( + PxRigidBody& body, PxScene& scene, const PxVec3& unitDir, const PxReal distance, + PxHitFlags outputFlags, + PxSweepHit* touchHitBuffer, PxU32* touchHitShapeIndices, PxU32 touchHitBufferSize, + PxSweepHit& block, PxI32& blockingShapeIndex, bool& overflow, + const PxQueryFilterData& filterData = PxQueryFilterData(), + PxQueryFilterCallback* filterCall = NULL, + const PxQueryCache* cache = NULL, const PxReal inflation = 0.0f); + + + /** + \brief Compute the change to linear and angular velocity that would occur if an impulsive force and torque were to be applied to a specified rigid body. + + The rigid body is left unaffected unless a subsequent independent call is executed that actually applies the computed changes to velocity and angular velocity. + + \note if this call is used to determine the velocity delta for an articulation link, only the mass properties of the link are taken into account. + + @see PxRigidBody::getLinearVelocity, PxRigidBody::setLinearVelocity, PxRigidBody::getAngularVelocity, PxRigidBody::setAngularVelocity + + \param[in] body The body under consideration. + \param[in] impulsiveForce The impulsive force that would be applied to the specified rigid body. + \param[in] impulsiveTorque The impulsive torque that would be applied to the specified rigid body. + \param[out] deltaLinearVelocity The change in linear velocity that would arise if impulsiveForce was to be applied to the specified rigid body. + \param[out] deltaAngularVelocity The change in angular velocity that would arise if impulsiveTorque was to be applied to the specified rigid body. + */ + static void computeVelocityDeltaFromImpulse(const PxRigidBody& body, const PxVec3& impulsiveForce, const PxVec3& impulsiveTorque, PxVec3& deltaLinearVelocity, PxVec3& deltaAngularVelocity); + + /** + \brief Computes the linear and angular velocity change vectors for a given impulse at a world space position taking a mass and inertia scale into account + + This function is useful for extracting the respective linear and angular velocity changes from a contact or joint when the mass/inertia ratios have been adjusted. + + \note if this call is used to determine the velocity delta for an articulation link, only the mass properties of the link are taken into account. + + \param[in] body The rigid body + \param[in] globalPose The body's world space transform + \param[in] point The point in world space where the impulse is applied + \param[in] impulse The impulse vector in world space + \param[in] invMassScale The inverse mass scale + \param[in] invInertiaScale The inverse inertia scale + \param[out] deltaLinearVelocity The linear velocity change + \param[out] deltaAngularVelocity The angular velocity change + */ + + static void computeVelocityDeltaFromImpulse(const PxRigidBody& body, const PxTransform& globalPose, const PxVec3& point, const PxVec3& impulse, const PxReal invMassScale, + const PxReal invInertiaScale, PxVec3& deltaLinearVelocity, PxVec3& deltaAngularVelocity); + + /** + \brief Computes the linear and angular impulse vectors for a given impulse at a world space position taking a mass and inertia scale into account + + This function is useful for extracting the respective linear and angular impulses from a contact or joint when the mass/inertia ratios have been adjusted. + + \param[in] body The rigid body + \param[in] globalPose The body's world space transform + \param[in] point The point in world space where the impulse is applied + \param[in] impulse The impulse vector in world space + \param[in] invMassScale The inverse mass scale + \param[in] invInertiaScale The inverse inertia scale + \param[out] linearImpulse The linear impulse + \param[out] angularImpulse The angular impulse + */ + static void computeLinearAngularImpulse(const PxRigidBody& body, const PxTransform& globalPose, const PxVec3& point, const PxVec3& impulse, const PxReal invMassScale, + const PxReal invInertiaScale, PxVec3& linearImpulse, PxVec3& angularImpulse); + + +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/extensions/PxSceneQueryExt.h b/sources/PhysX/PhysX/include/extensions/PxSceneQueryExt.h new file mode 100644 index 00000000..6f08fe80 --- /dev/null +++ b/sources/PhysX/PhysX/include/extensions/PxSceneQueryExt.h @@ -0,0 +1,309 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_EXTENSIONS_SCENE_QUERY_H +#define PX_PHYSICS_EXTENSIONS_SCENE_QUERY_H +/** \addtogroup extensions + @{ +*/ + +#include "PxPhysXConfig.h" + +#include "PxScene.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +// These types have been deprecated (removed) in PhysX 3.4. We typedef them to the new types here for easy migration from 3.3 to 3.4. +typedef PxQueryHit PxSceneQueryHit; +typedef PxQueryFilterData PxSceneQueryFilterData; +typedef PxQueryFilterCallback PxSceneQueryFilterCallback; +typedef PxQueryCache PxSceneQueryCache; +typedef PxHitFlag PxSceneQueryFlag; +typedef PxHitFlags PxSceneQueryFlags; + +/** +\brief utility functions for use with PxScene, related to scene queries. + +Some of these functions have been deprecated (removed) in PhysX 3.4. We re-implement them here for easy migration from 3.3 to 3.4. + +@see PxShape +*/ + +class PxSceneQueryExt +{ +public: + + /** + \brief Raycast returning any blocking hit, not necessarily the closest. + + Returns whether any rigid actor is hit along the ray. + + \note Shooting a ray from within an object leads to different results depending on the shape type. Please check the details in article SceneQuery. User can ignore such objects by using one of the provided filter mechanisms. + + \param[in] scene The scene + \param[in] origin Origin of the ray. + \param[in] unitDir Normalized direction of the ray. + \param[in] distance Length of the ray. Needs to be larger than 0. + \param[out] hit Raycast hit information. + \param[in] filterData Filtering data and simple logic. + \param[in] filterCall Custom filtering logic (optional). Only used if the corresponding #PxHitFlag flags are set. If NULL, all hits are assumed to be blocking. + \param[in] cache Cached hit shape (optional). Ray is tested against cached shape first. If no hit is found the ray gets queried against the scene. + Note: Filtering is not executed for a cached shape if supplied; instead, if a hit is found, it is assumed to be a blocking hit. + Note: Using past touching hits as cache will produce incorrect behavior since the cached hit will always be treated as blocking. + \return True if a blocking hit was found. + + @see PxSceneQueryFilterData PxSceneQueryFilterCallback PxSceneQueryCache PxSceneQueryHit + */ + static bool raycastAny( const PxScene& scene, + const PxVec3& origin, const PxVec3& unitDir, const PxReal distance, + PxSceneQueryHit& hit, const PxSceneQueryFilterData& filterData = PxSceneQueryFilterData(), + PxSceneQueryFilterCallback* filterCall = NULL, const PxSceneQueryCache* cache = NULL); + + /** + \brief Raycast returning a single result. + + Returns the first rigid actor that is hit along the ray. Data for a blocking hit will be returned as specified by the outputFlags field. Touching hits will be ignored. + + \note Shooting a ray from within an object leads to different results depending on the shape type. Please check the details in article SceneQuery. User can ignore such objects by using one of the provided filter mechanisms. + + \param[in] scene The scene + \param[in] origin Origin of the ray. + \param[in] unitDir Normalized direction of the ray. + \param[in] distance Length of the ray. Needs to be larger than 0. + \param[in] outputFlags Specifies which properties should be written to the hit information + \param[out] hit Raycast hit information. + \param[in] filterData Filtering data and simple logic. + \param[in] filterCall Custom filtering logic (optional). Only used if the corresponding #PxHitFlag flags are set. If NULL, all hits are assumed to be blocking. + \param[in] cache Cached hit shape (optional). Ray is tested against cached shape first then against the scene. + Note: Filtering is not executed for a cached shape if supplied; instead, if a hit is found, it is assumed to be a blocking hit. + Note: Using past touching hits as cache will produce incorrect behavior since the cached hit will always be treated as blocking. + \return True if a blocking hit was found. + + @see PxSceneQueryFlags PxRaycastHit PxSceneQueryFilterData PxSceneQueryFilterCallback PxSceneQueryCache + */ + static bool raycastSingle( const PxScene& scene, + const PxVec3& origin, const PxVec3& unitDir, const PxReal distance, + PxSceneQueryFlags outputFlags, PxRaycastHit& hit, + const PxSceneQueryFilterData& filterData = PxSceneQueryFilterData(), + PxSceneQueryFilterCallback* filterCall = NULL, const PxSceneQueryCache* cache = NULL); + + /** + \brief Raycast returning multiple results. + + Find all rigid actors that get hit along the ray. Each result contains data as specified by the outputFlags field. + + \note Touching hits are not ordered. + + \note Shooting a ray from within an object leads to different results depending on the shape type. Please check the details in article SceneQuery. User can ignore such objects by using one of the provided filter mechanisms. + + \param[in] scene The scene + \param[in] origin Origin of the ray. + \param[in] unitDir Normalized direction of the ray. + \param[in] distance Length of the ray. Needs to be larger than 0. + \param[in] outputFlags Specifies which properties should be written to the hit information + \param[out] hitBuffer Raycast hit information buffer. If the buffer overflows, the blocking hit is returned as the last entry together with an arbitrary subset + of the nearer touching hits (typically the query should be restarted with a larger buffer). + \param[in] hitBufferSize Size of the hit buffer. + \param[out] blockingHit True if a blocking hit was found. If found, it is the last in the buffer, preceded by any touching hits which are closer. Otherwise the touching hits are listed. + \param[in] filterData Filtering data and simple logic. + \param[in] filterCall Custom filtering logic (optional). Only used if the corresponding #PxHitFlag flags are set. If NULL, all hits are assumed to be touching. + \param[in] cache Cached hit shape (optional). Ray is tested against cached shape first then against the scene. + Note: Filtering is not executed for a cached shape if supplied; instead, if a hit is found, it is assumed to be a blocking hit. + Note: Using past touching hits as cache will produce incorrect behavior since the cached hit will always be treated as blocking. + \return Number of hits in the buffer, or -1 if the buffer overflowed. + + @see PxSceneQueryFlags PxRaycastHit PxSceneQueryFilterData PxSceneQueryFilterCallback PxSceneQueryCache + */ + static PxI32 raycastMultiple( const PxScene& scene, + const PxVec3& origin, const PxVec3& unitDir, const PxReal distance, + PxSceneQueryFlags outputFlags, + PxRaycastHit* hitBuffer, PxU32 hitBufferSize, bool& blockingHit, + const PxSceneQueryFilterData& filterData = PxSceneQueryFilterData(), + PxSceneQueryFilterCallback* filterCall = NULL, const PxSceneQueryCache* cache = NULL); + + /** + \brief Sweep returning any blocking hit, not necessarily the closest. + + Returns whether any rigid actor is hit along the sweep path. + + \note If a shape from the scene is already overlapping with the query shape in its starting position, behavior is controlled by the PxSceneQueryFlag::eINITIAL_OVERLAP flag. + + \param[in] scene The scene + \param[in] geometry Geometry of object to sweep (supported types are: box, sphere, capsule, convex). + \param[in] pose Pose of the sweep object. + \param[in] unitDir Normalized direction of the sweep. + \param[in] distance Sweep distance. Needs to be larger than 0. Will be clamped to PX_MAX_SWEEP_DISTANCE. + \param[in] queryFlags Combination of PxSceneQueryFlag defining the query behavior + \param[out] hit Sweep hit information. + \param[in] filterData Filtering data and simple logic. + \param[in] filterCall Custom filtering logic (optional). Only used if the corresponding #PxHitFlag flags are set. If NULL, all hits are assumed to be blocking. + \param[in] cache Cached hit shape (optional). Sweep is performed against cached shape first. If no hit is found the sweep gets queried against the scene. + Note: Filtering is not executed for a cached shape if supplied; instead, if a hit is found, it is assumed to be a blocking hit. + Note: Using past touching hits as cache will produce incorrect behavior since the cached hit will always be treated as blocking. + \param[in] inflation This parameter creates a skin around the swept geometry which increases its extents for sweeping. The sweep will register a hit as soon as the skin touches a shape, and will return the corresponding distance and normal. + \return True if a blocking hit was found. + + @see PxSceneQueryFilterData PxSceneQueryFilterCallback PxSceneQueryHit PxSceneQueryCache + */ + static bool sweepAny( const PxScene& scene, + const PxGeometry& geometry, const PxTransform& pose, const PxVec3& unitDir, const PxReal distance, + PxSceneQueryFlags queryFlags, + PxSceneQueryHit& hit, + const PxSceneQueryFilterData& filterData = PxSceneQueryFilterData(), + PxSceneQueryFilterCallback* filterCall = NULL, + const PxSceneQueryCache* cache = NULL, + PxReal inflation = 0.0f); + + /** + \brief Sweep returning a single result. + + Returns the first rigid actor that is hit along the ray. Data for a blocking hit will be returned as specified by the outputFlags field. Touching hits will be ignored. + + \note If a shape from the scene is already overlapping with the query shape in its starting position, behavior is controlled by the PxSceneQueryFlag::eINITIAL_OVERLAP flag. + + \param[in] scene The scene + \param[in] geometry Geometry of object to sweep (supported types are: box, sphere, capsule, convex). + \param[in] pose Pose of the sweep object. + \param[in] unitDir Normalized direction of the sweep. + \param[in] distance Sweep distance. Needs to be larger than 0. Will be clamped to PX_MAX_SWEEP_DISTANCE. + \param[in] outputFlags Specifies which properties should be written to the hit information. + \param[out] hit Sweep hit information. + \param[in] filterData Filtering data and simple logic. + \param[in] filterCall Custom filtering logic (optional). Only used if the corresponding #PxHitFlag flags are set. If NULL, all hits are assumed to be blocking. + \param[in] cache Cached hit shape (optional). Sweep is performed against cached shape first then against the scene. + Note: Filtering is not executed for a cached shape if supplied; instead, if a hit is found, it is assumed to be a blocking hit. + Note: Using past touching hits as cache will produce incorrect behavior since the cached hit will always be treated as blocking. + \param[in] inflation This parameter creates a skin around the swept geometry which increases its extents for sweeping. The sweep will register a hit as soon as the skin touches a shape, and will return the corresponding distance and normal. + \return True if a blocking hit was found. + + @see PxSceneQueryFlags PxSweepHit PxSceneQueryFilterData PxSceneQueryFilterCallback PxSceneQueryCache + */ + static bool sweepSingle(const PxScene& scene, + const PxGeometry& geometry, const PxTransform& pose, const PxVec3& unitDir, const PxReal distance, + PxSceneQueryFlags outputFlags, + PxSweepHit& hit, + const PxSceneQueryFilterData& filterData = PxSceneQueryFilterData(), + PxSceneQueryFilterCallback* filterCall = NULL, + const PxSceneQueryCache* cache = NULL, + PxReal inflation=0.0f); + + /** + \brief Sweep returning multiple results. + + Find all rigid actors that get hit along the sweep. Each result contains data as specified by the outputFlags field. + + \note Touching hits are not ordered. + + \note If a shape from the scene is already overlapping with the query shape in its starting position, behavior is controlled by the PxSceneQueryFlag::eINITIAL_OVERLAP flag. + + \param[in] scene The scene + \param[in] geometry Geometry of object to sweep (supported types are: box, sphere, capsule, convex). + \param[in] pose Pose of the sweep object. + \param[in] unitDir Normalized direction of the sweep. + \param[in] distance Sweep distance. Needs to be larger than 0. Will be clamped to PX_MAX_SWEEP_DISTANCE. + \param[in] outputFlags Specifies which properties should be written to the hit information. + \param[out] hitBuffer Sweep hit information buffer. If the buffer overflows, the blocking hit is returned as the last entry together with an arbitrary subset + of the nearer touching hits (typically the query should be restarted with a larger buffer). + \param[in] hitBufferSize Size of the hit buffer. + \param[out] blockingHit True if a blocking hit was found. If found, it is the last in the buffer, preceded by any touching hits which are closer. Otherwise the touching hits are listed. + \param[in] filterData Filtering data and simple logic. + \param[in] filterCall Custom filtering logic (optional). Only used if the corresponding #PxHitFlag flags are set. If NULL, all hits are assumed to be touching. + \param[in] cache Cached hit shape (optional). Sweep is performed against cached shape first then against the scene. + Note: Filtering is not executed for a cached shape if supplied; instead, if a hit is found, it is assumed to be a blocking hit. + Note: Using past touching hits as cache will produce incorrect behavior since the cached hit will always be treated as blocking. + \param[in] inflation This parameter creates a skin around the swept geometry which increases its extents for sweeping. The sweep will register a hit as soon as the skin touches a shape, and will return the corresponding distance and normal. + \return Number of hits in the buffer, or -1 if the buffer overflowed. + + @see PxSceneQueryFlags PxSweepHit PxSceneQueryFilterData PxSceneQueryFilterCallback PxSceneQueryCache + */ + static PxI32 sweepMultiple( const PxScene& scene, + const PxGeometry& geometry, const PxTransform& pose, const PxVec3& unitDir, const PxReal distance, + PxSceneQueryFlags outputFlags, PxSweepHit* hitBuffer, PxU32 hitBufferSize, bool& blockingHit, + const PxSceneQueryFilterData& filterData = PxSceneQueryFilterData(), + PxSceneQueryFilterCallback* filterCall = NULL, const PxSceneQueryCache* cache = NULL, + PxReal inflation = 0.0f); + + /** + \brief Test overlap between a geometry and objects in the scene. + + \note Filtering: Overlap tests do not distinguish between touching and blocking hit types. Both get written to the hit buffer. + + \note PxHitFlag::eMESH_MULTIPLE and PxHitFlag::eMESH_BOTH_SIDES have no effect in this case + + \param[in] scene The scene + \param[in] geometry Geometry of object to check for overlap (supported types are: box, sphere, capsule, convex). + \param[in] pose Pose of the object. + \param[out] hitBuffer Buffer to store the overlapping objects to. If the buffer overflows, an arbitrary subset of overlapping objects is stored (typically the query should be restarted with a larger buffer). + \param[in] hitBufferSize Size of the hit buffer. + \param[in] filterData Filtering data and simple logic. + \param[in] filterCall Custom filtering logic (optional). Only used if the corresponding #PxHitFlag flags are set. If NULL, all hits are assumed to overlap. + \return Number of hits in the buffer, or -1 if the buffer overflowed. + + @see PxSceneQueryFlags PxSceneQueryFilterData PxSceneQueryFilterCallback + */ + static PxI32 overlapMultiple( const PxScene& scene, + const PxGeometry& geometry, const PxTransform& pose, + PxOverlapHit* hitBuffer, PxU32 hitBufferSize, + const PxSceneQueryFilterData& filterData = PxSceneQueryFilterData(), + PxSceneQueryFilterCallback* filterCall = NULL); + + /** + \brief Test returning, for a given geometry, any overlapping object in the scene. + + \note Filtering: Overlap tests do not distinguish between touching and blocking hit types. Both trigger a hit. + + \note PxHitFlag::eMESH_MULTIPLE and PxHitFlag::eMESH_BOTH_SIDES have no effect in this case + + \param[in] scene The scene + \param[in] geometry Geometry of object to check for overlap (supported types are: box, sphere, capsule, convex). + \param[in] pose Pose of the object. + \param[out] hit Pointer to store the overlapping object to. + \param[in] filterData Filtering data and simple logic. + \param[in] filterCall Custom filtering logic (optional). Only used if the corresponding #PxHitFlag flags are set. If NULL, all hits are assumed to overlap. + \return True if an overlap was found. + + @see PxSceneQueryFlags PxSceneQueryFilterData PxSceneQueryFilterCallback + */ + static bool overlapAny( const PxScene& scene, + const PxGeometry& geometry, const PxTransform& pose, + PxOverlapHit& hit, + const PxSceneQueryFilterData& filterData = PxSceneQueryFilterData(), + PxSceneQueryFilterCallback* filterCall = NULL); +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/extensions/PxSerialization.h b/sources/PhysX/PhysX/include/extensions/PxSerialization.h new file mode 100644 index 00000000..54e5cdd0 --- /dev/null +++ b/sources/PhysX/PhysX/include/extensions/PxSerialization.h @@ -0,0 +1,290 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_SERIALIZATION_H +#define PX_SERIALIZATION_H +/** \addtogroup extensions + @{ +*/ + +#include "PxPhysXConfig.h" +#include "common/PxBase.h" +#include "cooking/PxCooking.h" +#include "foundation/PxIO.h" +#include "common/PxTolerancesScale.h" +#include "common/PxTypeInfo.h" +#include "common/PxStringTable.h" + +/** +PX_BINARY_SERIAL_VERSION is used to version the PhysX binary data and meta data. The global unique identifier of the PhysX SDK needs to match +the one in the data and meta data, otherwise they are considered incompatible. A 32 character wide GUID can be generated with https://www.guidgenerator.com/ for example. +*/ +#define PX_BINARY_SERIAL_VERSION "F193874828914B3A8AC4EFE75AED0247" + + +#if !PX_DOXYGEN +namespace physx +{ +#endif + + class PxBinaryConverter; + +/** +\brief Utility functions for serialization + +@see PxCollection, PxSerializationRegistry +*/ +class PxSerialization +{ +public: + /** + \brief Additional PxScene and PxPhysics options stored in XML serialized data. + + The PxXmlMiscParameter parameter can be serialized and deserialized along with PxCollection instances (XML only). + This is for application use only and has no impact on how objects are serialized or deserialized. + @see PxSerialization::createCollectionFromXml, PxSerialization::serializeCollectionToXml + */ + struct PxXmlMiscParameter + { + /** + \brief Up vector for the scene reference coordinate system. + */ + PxVec3 upVector; + + /** + \brief Tolerances scale to be used for the scene. + */ + PxTolerancesScale scale; + + PxXmlMiscParameter() : upVector(0) {} + PxXmlMiscParameter(PxVec3& inUpVector, PxTolerancesScale inScale) : upVector(inUpVector), scale(inScale) {} + }; + + /** + \brief Returns whether the collection is serializable with the externalReferences collection. + + Some definitions to explain whether a collection can be serialized or not: + + For definitions of requires and complete see #PxSerialization::complete + + A serializable object is subordinate if it cannot be serialized on its own + The following objects are subordinate: + - articulation links + - articulation joints + - joints + + A collection C can be serialized with external references collection D iff + - C is complete relative to D (no dangling references) + - Every object in D required by an object in C has a valid ID (no unnamed references) + - Every subordinate object in C is required by another object in C (no orphans) + + \param[in] collection Collection to be checked + \param[in] sr PxSerializationRegistry instance with information about registered classes. + \param[in] externalReferences the external References collection + \return Whether the collection is serializable + @see PxSerialization::complete, PxSerialization::serializeCollectionToBinary, PxSerialization::serializeCollectionToXml, PxSerializationRegistry + */ + static bool isSerializable(PxCollection& collection, PxSerializationRegistry& sr, const PxCollection* externalReferences = NULL); + + /** + \brief Adds to a collection all objects such that it can be successfully serialized. + + A collection C is complete relative to an other collection D if every object required by C is either in C or D. + This function adds objects to a collection, such that it becomes complete with respect to the exceptFor collection. + Completeness is needed for serialization. See #PxSerialization::serializeCollectionToBinary, + #PxSerialization::serializeCollectionToXml. + + Sdk objects require other sdk object according to the following rules: + - joints require their actors and constraint + - rigid actors require their shapes + - shapes require their material(s) and mesh (triangle mesh, convex mesh or height field), if any + - articulations require their links and joints + - aggregates require their actors + + If followJoints is specified another rule is added: + - actors require their joints + + Specifying followJoints will make whole jointed actor chains being added to the collection. Following chains + is interrupted whenever a object in exceptFor is encountered. + + \param[in,out] collection Collection which is completed + \param[in] sr PxSerializationRegistry instance with information about registered classes. + \param[in] exceptFor Optional exemption collection + \param[in] followJoints Specifies whether joints should be added for jointed actors + @see PxCollection, PxSerialization::serializeCollectionToBinary, PxSerialization::serializeCollectionToXml, PxSerializationRegistry + */ + static void complete(PxCollection& collection, PxSerializationRegistry& sr, const PxCollection* exceptFor = NULL, bool followJoints = false); + + /** + \brief Creates PxSerialObjectId values for unnamed objects in a collection. + + Creates PxSerialObjectId names for unnamed objects in a collection starting at a base value and incrementing, + skipping values that are already assigned to objects in the collection. + + \param[in,out] collection Collection for which names are created + \param[in] base Start address for PxSerialObjectId names + @see PxCollection + */ + static void createSerialObjectIds(PxCollection& collection, const PxSerialObjectId base); + + /** + \brief Creates a PxCollection from XML data. + + \param inputData The input data containing the XML collection. + \param cooking PxCooking instance used for sdk object instantiation. + \param sr PxSerializationRegistry instance with information about registered classes. + \param externalRefs PxCollection used to resolve external references. + \param stringTable PxStringTable instance used for storing object names. + \param outArgs Optional parameters of physics and scene deserialized from XML. See #PxSerialization::PxXmlMiscParameter + \return a pointer to a PxCollection if successful or NULL if it failed. + + @see PxCollection, PxSerializationRegistry, PxInputData, PxStringTable, PxCooking, PxSerialization::PxXmlMiscParameter + */ + static PxCollection* createCollectionFromXml(PxInputData& inputData, PxCooking& cooking, PxSerializationRegistry& sr, const PxCollection* externalRefs = NULL, PxStringTable* stringTable = NULL, PxXmlMiscParameter* outArgs = NULL); + + /** + \brief Deserializes a PxCollection from memory. + + Creates a collection from memory. If the collection has external dependencies another collection + can be provided to resolve these. + + The memory block provided has to be 128 bytes aligned and contain a contiguous serialized collection as written + by PxSerialization::serializeCollectionToBinary. The contained binary data needs to be compatible with the current binary format version + which is defined by "PX_PHYSICS_VERSION_MAJOR.PX_PHYSICS_VERSION_MINOR.PX_PHYSICS_VERSION_BUGFIX-PX_BINARY_SERIAL_VERSION". + For a list of compatible sdk releases refer to the documentation of PX_BINARY_SERIAL_VERSION. + + \param[in] memBlock Pointer to memory block containing the serialized collection + \param[in] sr PxSerializationRegistry instance with information about registered classes. + \param[in] externalRefs Collection to resolve external dependencies + + @see PxCollection, PxSerialization::complete, PxSerialization::serializeCollectionToBinary, PxSerializationRegistry, PX_BINARY_SERIAL_VERSION + */ + static PxCollection* createCollectionFromBinary(void* memBlock, PxSerializationRegistry& sr, const PxCollection* externalRefs = NULL); + + /** + \brief Serializes a physics collection to an XML output stream. + + The collection to be serialized needs to be complete @see PxSerialization.complete. + Optionally the XML may contain meshes in binary cooked format for fast loading. It does this when providing a valid non-null PxCooking pointer. + + \note Serialization of objects in a scene that is simultaneously being simulated is not supported and leads to undefined behavior. + + \param outputStream Stream to save collection to. + \param collection PxCollection instance which is serialized. The collection needs to be complete with respect to the externalRefs collection. + \param sr PxSerializationRegistry instance with information about registered classes. + \param cooking Optional pointer to cooking instance. If provided, cooked mesh data is cached for fast loading. + \param externalRefs Collection containing external references. + \param inArgs Optional parameters of physics and scene serialized to XML along with the collection. See #PxSerialization::PxXmlMiscParameter + \return true if the collection is successfully serialized. + + @see PxCollection, PxOutputStream, PxSerializationRegistry, PxCooking, PxSerialization::PxXmlMiscParameter + */ + static bool serializeCollectionToXml(PxOutputStream& outputStream, PxCollection& collection, PxSerializationRegistry& sr, PxCooking* cooking = NULL, const PxCollection* externalRefs = NULL, PxXmlMiscParameter* inArgs = NULL); + + /** + \brief Serializes a collection to a binary stream. + + Serializes a collection to a stream. In order to resolve external dependencies the externalReferences collection has to be provided. + Optionally names of objects that where set for example with #PxActor::setName are serialized along with the objects. + + The collection can be successfully serialized if isSerializable(collection) returns true. See #isSerializable. + + The implementation of the output stream needs to fulfill the requirements on the memory block input taken by + PxSerialization::createCollectionFromBinary. + + \note Serialization of objects in a scene that is simultaneously being simulated is not supported and leads to undefined behavior. + + \param[out] outputStream into which the collection is serialized + \param[in] collection Collection to be serialized + \param[in] sr PxSerializationRegistry instance with information about registered classes. + \param[in] externalRefs Collection used to resolve external dependencies + \param[in] exportNames Specifies whether object names are serialized + \return Whether serialization was successful + + @see PxCollection, PxOutputStream, PxSerialization::complete, PxSerialization::createCollectionFromBinary, PxSerializationRegistry + */ + static bool serializeCollectionToBinary(PxOutputStream& outputStream, PxCollection& collection, PxSerializationRegistry& sr, const PxCollection* externalRefs = NULL, bool exportNames = false ); + + /** + \brief Serializes a collection to a binary stream. + + Convenience function that serializes a collection to a stream while rebasing memory addresses and handles + to achieve a deterministic output, independent of the PhysX runtime environment the objects have been created in. + + The same functionality can be achieved by manually + - creating a binary data stream with PxSerialization::serializeCollectionToBinary + - producing the binary meta data of the current runtime platform with PxSerialization::dumpBinaryMetaData + - converting the binary data stream with the PxBinaryConverter, using the binary meta for both source and destination + + @see PxSerialization::serializeCollectionToBinary, PxSerialization::dumpBinaryMetaData, PxBinaryConverter + */ + static bool serializeCollectionToBinaryDeterministic(PxOutputStream& outputStream, PxCollection& collection, PxSerializationRegistry& sr, const PxCollection* externalRefs = NULL, bool exportNames = false); + + /** + \brief Dumps the binary meta-data to a stream. + + A meta-data file contains information about the SDK's internal classes and about custom user types ready + for serialization. Such a file is needed to convert binary-serialized data from one platform to another (re-targeting). + The converter needs meta-data files for the source and target platforms to perform conversions. + + Custom user types can be supported with PxSerializationRegistry::registerBinaryMetaDataCallback (see the guide for more information). + + \param[out] outputStream Stream to write meta data to + \param[in] sr PxSerializationRegistry instance with information about registered classes used for conversion. + + @see PxOutputStream, PxSerializationRegistry + */ + static void dumpBinaryMetaData(PxOutputStream& outputStream, PxSerializationRegistry& sr); + + /** + \brief Creates binary converter for re-targeting binary-serialized data. + + \return Binary converter instance. + */ + static PxBinaryConverter* createBinaryConverter(); + + /** + \brief Creates an application managed registry for serialization. + + \param[in] physics Physics SDK to generate create serialization registry + + \return PxSerializationRegistry instance. + + @see PxSerializationRegistry + */ + static PxSerializationRegistry* createSerializationRegistry(PxPhysics& physics); +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/extensions/PxShapeExt.h b/sources/PhysX/PhysX/include/extensions/PxShapeExt.h new file mode 100644 index 00000000..ce4440a8 --- /dev/null +++ b/sources/PhysX/PhysX/include/extensions/PxShapeExt.h @@ -0,0 +1,158 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_EXTENSIONS_SHAPE_H +#define PX_PHYSICS_EXTENSIONS_SHAPE_H +/** \addtogroup extensions + @{ +*/ + +#include "PxPhysXConfig.h" + +#include "PxShape.h" +#include "PxRigidActor.h" +#include "geometry/PxGeometryQuery.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief utility functions for use with PxShape + +@see PxShape +*/ + +class PxShapeExt +{ +public: + /** + \brief Retrieves the world space pose of the shape. + + \param[in] shape The shape for which to get the global pose. + \param[in] actor The actor to which the shape is attached + + \return Global pose of shape. + */ + static PX_INLINE PxTransform getGlobalPose(const PxShape& shape, const PxRigidActor& actor) + { + return actor.getGlobalPose() * shape.getLocalPose(); + } + + /** + \brief Raycast test against the shape. + + \param[in] shape the shape + \param[in] actor the actor to which the shape is attached + \param[in] rayOrigin The origin of the ray to test the geometry object against + \param[in] rayDir The direction of the ray to test the geometry object against + \param[in] maxDist Maximum ray length + \param[in] hitFlags Specify which properties per hit should be computed and written to result hit array. Combination of #PxHitFlag flags + \param[in] maxHits max number of returned hits = size of 'rayHits' buffer + \param[out] rayHits Raycast hits information + \return Number of hits between the ray and the shape + + @see PxRaycastHit PxTransform + */ + static PX_INLINE PxU32 raycast(const PxShape& shape, const PxRigidActor& actor, + const PxVec3& rayOrigin, const PxVec3& rayDir, PxReal maxDist, PxHitFlags hitFlags, + PxU32 maxHits, PxRaycastHit* rayHits) + { + return PxGeometryQuery::raycast( + rayOrigin, rayDir, shape.getGeometry().any(), getGlobalPose(shape, actor), maxDist, hitFlags, maxHits, rayHits); + } + + /** + \brief Test overlap between the shape and a geometry object + + \param[in] shape the shape + \param[in] actor the actor to which the shape is attached + \param[in] otherGeom The other geometry object to test overlap with + \param[in] otherGeomPose Pose of the other geometry object + \return True if the shape overlaps the geometry object + + @see PxGeometry PxTransform + */ + static PX_INLINE bool overlap(const PxShape& shape, const PxRigidActor& actor, + const PxGeometry& otherGeom, const PxTransform& otherGeomPose) + { + return PxGeometryQuery::overlap(shape.getGeometry().any(), getGlobalPose(shape, actor), otherGeom, otherGeomPose); + } + + /** + \brief Sweep a geometry object against the shape. + + Currently only box, sphere, capsule and convex mesh shapes are supported, i.e. the swept geometry object must be one of those types. + + \param[in] shape the shape + \param[in] actor the actor to which the shape is attached + \param[in] unitDir Normalized direction along which the geometry object should be swept. + \param[in] distance Sweep distance. Needs to be larger than 0. + \param[in] otherGeom The geometry object to sweep against the shape + \param[in] otherGeomPose Pose of the geometry object + \param[out] sweepHit The sweep hit information. Only valid if this method returns true. + \param[in] hitFlags Specify which properties per hit should be computed and written to result hit array. Combination of #PxHitFlag flags + \return True if the swept geometry object hits the shape + + @see PxGeometry PxTransform PxSweepHit + */ + static PX_INLINE bool sweep(const PxShape& shape, const PxRigidActor& actor, + const PxVec3& unitDir, const PxReal distance, const PxGeometry& otherGeom, const PxTransform& otherGeomPose, + PxSweepHit& sweepHit, PxHitFlags hitFlags) + { + return PxGeometryQuery::sweep(unitDir, distance, otherGeom, otherGeomPose, shape.getGeometry().any(), getGlobalPose(shape, actor), sweepHit, hitFlags); + } + + + /** + \brief Retrieves the axis aligned bounding box enclosing the shape. + + \return The shape's bounding box. + + \param[in] shape the shape + \param[in] actor the actor to which the shape is attached + \param[in] inflation Scale factor for computed world bounds. Box extents are multiplied by this value. + + @see PxBounds3 + */ + static PX_INLINE PxBounds3 getWorldBounds(const PxShape& shape, const PxRigidActor& actor, float inflation=1.01f) + { + return PxGeometryQuery::getWorldBounds(shape.getGeometry().any(), getGlobalPose(shape, actor), inflation); + } + +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/extensions/PxSimpleFactory.h b/sources/PhysX/PhysX/include/extensions/PxSimpleFactory.h new file mode 100644 index 00000000..d6e423dc --- /dev/null +++ b/sources/PhysX/PhysX/include/extensions/PxSimpleFactory.h @@ -0,0 +1,337 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_EXTENSIONS_SIMPLE_FACTORY_H +#define PX_PHYSICS_EXTENSIONS_SIMPLE_FACTORY_H +/** \addtogroup extensions + @{ +*/ + +#include "common/PxPhysXCommonConfig.h" +#include "foundation/PxTransform.h" +#include "foundation/PxPlane.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + + class PxPhysics; + class PxMaterial; + class PxRigidActor; + class PxRigidDynamic; + class PxRigidStatic; + class PxGeometry; + class PxShape; + + +/** \brief simple method to create a PxRigidDynamic actor with a single PxShape. + + \param[in] sdk the PxPhysics object + \param[in] transform the global pose of the new object + \param[in] geometry the geometry of the new object's shape, which must be a sphere, capsule, box or convex + \param[in] material the material for the new object's shape + \param[in] density the density of the new object. Must be greater than zero. + \param[in] shapeOffset an optional offset for the new shape, defaults to identity + + \return a new dynamic actor with the PxRigidBodyFlag, or NULL if it could + not be constructed + + @see PxRigidDynamic PxShapeFlag +*/ + +PxRigidDynamic* PxCreateDynamic(PxPhysics& sdk, + const PxTransform& transform, + const PxGeometry& geometry, + PxMaterial& material, + PxReal density, + const PxTransform& shapeOffset = PxTransform(PxIdentity)); + + +/** \brief simple method to create a PxRigidDynamic actor with a single PxShape. + + \param[in] sdk the PxPhysics object + \param[in] transform the transform of the new object + \param[in] shape the shape of the new object + \param[in] density the density of the new object. Must be greater than zero. + + \return a new dynamic actor with the PxRigidBodyFlag, or NULL if it could + not be constructed + + @see PxRigidDynamic PxShapeFlag +*/ + +PxRigidDynamic* PxCreateDynamic(PxPhysics& sdk, + const PxTransform& transform, + PxShape& shape, + PxReal density); + + +/** \brief simple method to create a kinematic PxRigidDynamic actor with a single PxShape. + + \param[in] sdk the PxPhysics object + \param[in] transform the global pose of the new object + \param[in] geometry the geometry of the new object's shape + \param[in] material the material for the new object's shape + \param[in] density the density of the new object. Must be greater than zero if the object is to participate in simulation. + \param[in] shapeOffset an optional offset for the new shape, defaults to identity + + \note unlike PxCreateDynamic, the geometry is not restricted to box, capsule, sphere or convex. However, + kinematics of other geometry types may not participate in simulation collision and may be used only for + triggers or scene queries of moving objects under animation control. In this case the density parameter + will be ignored and the created shape will be set up as a scene query only shape (see #PxShapeFlag::eSCENE_QUERY_SHAPE) + + \return a new dynamic actor with the PxRigidBodyFlag::eKINEMATIC set, or NULL if it could + not be constructed + + @see PxRigidDynamic PxShapeFlag +*/ + +PxRigidDynamic* PxCreateKinematic(PxPhysics& sdk, + const PxTransform& transform, + const PxGeometry& geometry, + PxMaterial& material, + PxReal density, + const PxTransform& shapeOffset = PxTransform(PxIdentity)); + + +/** \brief simple method to create a kinematic PxRigidDynamic actor with a single PxShape. + + \param[in] sdk the PxPhysics object + \param[in] transform the global pose of the new object + \param[in] density the density of the new object. Must be greater than zero if the object is to participate in simulation. + \param[in] shape the shape of the new object + + \note unlike PxCreateDynamic, the geometry is not restricted to box, capsule, sphere or convex. However, + kinematics of other geometry types may not participate in simulation collision and may be used only for + triggers or scene queries of moving objects under animation control. In this case the density parameter + will be ignored and the created shape will be set up as a scene query only shape (see #PxShapeFlag::eSCENE_QUERY_SHAPE) + + \return a new dynamic actor with the PxRigidBodyFlag::eKINEMATIC set, or NULL if it could + not be constructed + + @see PxRigidDynamic PxShapeFlag +*/ + +PxRigidDynamic* PxCreateKinematic(PxPhysics& sdk, + const PxTransform& transform, + PxShape& shape, + PxReal density); + + +/** \brief simple method to create a PxRigidStatic actor with a single PxShape. + + \param[in] sdk the PxPhysics object + \param[in] transform the global pose of the new object + \param[in] geometry the geometry of the new object's shape + \param[in] material the material for the new object's shape + \param[in] shapeOffset an optional offset for the new shape, defaults to identity + + \return a new static actor, or NULL if it could not be constructed + + @see PxRigidStatic +*/ + +PxRigidStatic* PxCreateStatic(PxPhysics& sdk, + const PxTransform& transform, + const PxGeometry& geometry, + PxMaterial& material, + const PxTransform& shapeOffset = PxTransform(PxIdentity)); + + +/** \brief simple method to create a PxRigidStatic actor with a single PxShape. + + \param[in] sdk the PxPhysics object + \param[in] transform the global pose of the new object + \param[in] shape the new object's shape + + \return a new static actor, or NULL if it could not be constructed + + @see PxRigidStatic +*/ + +PxRigidStatic* PxCreateStatic(PxPhysics& sdk, + const PxTransform& transform, + PxShape& shape); + + +/** \brief simple method to create a PxRigidStatic actor with a single PxShape. + + \param[in] sdk the PxPhysics object + \param[in] transform the global pose of the new object + \param[in] shape the new object's shape + + \return a new static actor, or NULL if it could not be constructed + + @see PxRigidStatic +*/ + +PxRigidStatic* PxCreateStatic(PxPhysics& sdk, + const PxTransform& transform, + PxShape& shape); + + +/** +\brief create a shape by copying attributes from another shape + +The function clones a PxShape. The following properties are copied: +- geometry +- flags +- materials +- actor-local pose +- contact offset +- rest offset +- simulation filter data +- query filter data + +The following are not copied and retain their default values: +- name +- user data + +\param[in] physicsSDK - the physics SDK used to allocate the shape +\param[in] shape the shape from which to take the attributes. +\param[in] isExclusive whether the new shape should be an exclusive or shared shape. + +\return the newly-created rigid static + +*/ + +PxShape* PxCloneShape(PxPhysics& physicsSDK, + const PxShape& shape, + bool isExclusive); + + + +/** +\brief create a static body by copying attributes from another rigid actor + +The function clones a PxRigidDynamic or PxRigidStatic as a PxRigidStatic. A uniform scale is applied. The following properties are copied: +- shapes +- actor flags +- owner client and client behavior bits + +The following are not copied and retain their default values: +- name +- joints or observers +- aggregate or scene membership +- user data + +\note Transforms are not copied with bit-exact accuracy. + +\param[in] physicsSDK - the physics SDK used to allocate the rigid static +\param[in] actor the rigid actor from which to take the attributes. +\param[in] transform the transform of the new static. + +\return the newly-created rigid static + +*/ + +PxRigidStatic* PxCloneStatic(PxPhysics& physicsSDK, + const PxTransform& transform, + const PxRigidActor& actor); + + +/** +\brief create a dynamic body by copying attributes from an existing body + +The following properties are copied: +- shapes +- actor flags and rigidDynamic flags +- mass, moment of inertia, and center of mass frame +- linear and angular velocity +- linear and angular damping +- maximum angular velocity +- position and velocity solver iterations +- maximum depenetration velocity +- sleep threshold +- contact report threshold +- dominance group +- owner client and client behavior bits +- name pointer + +The following are not copied and retain their default values: +- name +- joints or observers +- aggregate or scene membership +- sleep timer +- user data + +\note Transforms are not copied with bit-exact accuracy. + +\param[in] physicsSDK PxPhysics - the physics SDK used to allocate the rigid static +\param[in] body the rigid dynamic to clone. +\param[in] transform the transform of the new dynamic + +\return the newly-created rigid static + +*/ + +PxRigidDynamic* PxCloneDynamic(PxPhysics& physicsSDK, + const PxTransform& transform, + const PxRigidDynamic& body); + + +/** \brief create a plane actor. The plane equation is n.x + d = 0 + + \param[in] sdk the PxPhysics object + \param[in] plane a plane of the form n.x + d = 0 + \param[in] material the material for the new object's shape + + \return a new static actor, or NULL if it could not be constructed + + @see PxRigidStatic +*/ + +PxRigidStatic* PxCreatePlane(PxPhysics& sdk, + const PxPlane& plane, + PxMaterial& material); + + +/** +\brief scale a rigid actor by a uniform scale + +The geometry and relative positions of the actor are multiplied by the given scale value. If the actor is a rigid body or an +articulation link and the scaleMassProps value is true, the mass properties are scaled assuming the density is constant: the +center of mass is linearly scaled, the mass is multiplied by the cube of the scale, and the inertia tensor by the fifth power of the scale. + +\param[in] actor a rigid actor +\param[in] scale the scale by which to multiply the actor. Must be >0. +\param[in] scaleMassProps whether to scale the mass properties +*/ + +void PxScaleRigidActor(PxRigidActor& actor, PxReal scale, bool scaleMassProps = true); + + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/extensions/PxSmoothNormals.h b/sources/PhysX/PhysX/include/extensions/PxSmoothNormals.h new file mode 100644 index 00000000..21d0d47f --- /dev/null +++ b/sources/PhysX/PhysX/include/extensions/PxSmoothNormals.h @@ -0,0 +1,61 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_EXTENSIONS_SMOOTH_NORMALS_H +#define PX_PHYSICS_EXTENSIONS_SMOOTH_NORMALS_H +/** \addtogroup extensions + @{ +*/ + +#include "common/PxPhysXCommonConfig.h" + +/** +\brief Builds smooth vertex normals over a mesh. + +- "smooth" because smoothing groups are not supported here +- takes angles into account for correct cube normals computation + +To use 32bit indices pass a pointer in dFaces and set wFaces to zero. Alternatively pass a pointer to +wFaces and set dFaces to zero. + +\param[in] nbTris Number of triangles +\param[in] nbVerts Number of vertices +\param[in] verts Array of vertices +\param[in] dFaces Array of dword triangle indices, or null +\param[in] wFaces Array of word triangle indices, or null +\param[out] normals Array of computed normals (assumes nbVerts vectors) +\param[in] flip Flips the normals or not +\return True on success. +*/ +PX_C_EXPORT bool PX_CALL_CONV PxBuildSmoothNormals(physx::PxU32 nbTris, physx::PxU32 nbVerts, const physx::PxVec3* verts, + const physx::PxU32* dFaces, const physx::PxU16* wFaces, physx::PxVec3* normals, bool flip); + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/extensions/PxSphericalJoint.h b/sources/PhysX/PhysX/include/extensions/PxSphericalJoint.h new file mode 100644 index 00000000..188ebfc4 --- /dev/null +++ b/sources/PhysX/PhysX/include/extensions/PxSphericalJoint.h @@ -0,0 +1,215 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_SPHERICALJOINT_H +#define PX_SPHERICALJOINT_H +/** \addtogroup extensions + @{ +*/ + +#include "extensions/PxJoint.h" +#include "extensions/PxJointLimit.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxSphericalJoint; + +/** +\brief Create a spherical joint. + + \param[in] physics The physics SDK + \param[in] actor0 An actor to which the joint is attached. NULL may be used to attach the joint to a specific point in the world frame + \param[in] localFrame0 The position and orientation of the joint relative to actor0 + \param[in] actor1 An actor to which the joint is attached. NULL may be used to attach the joint to a specific point in the world frame + \param[in] localFrame1 The position and orientation of the joint relative to actor1 + +@see PxSphericalJoint +*/ +PxSphericalJoint* PxSphericalJointCreate(PxPhysics& physics, PxRigidActor* actor0, const PxTransform& localFrame0, PxRigidActor* actor1, const PxTransform& localFrame1); + + +/** +\brief Flags specific to the spherical joint. + +@see PxSphericalJoint +*/ +struct PxSphericalJointFlag +{ + enum Enum + { + eLIMIT_ENABLED = 1<<1 //!< the cone limit for the spherical joint is enabled + }; +}; +typedef PxFlags PxSphericalJointFlags; +PX_FLAGS_OPERATORS(PxSphericalJointFlag::Enum, PxU16) + +/** +\brief A joint which behaves in a similar way to a ball and socket. + + A spherical joint removes all linear degrees of freedom from two objects. + + The position of the joint on each actor is specified by the origin of the body's joint frame. + + A spherical joint may have a cone limit, to restrict the motion to within a certain range. In + addition, the bodies may be projected together if the distance between them exceeds a given threshold. + + Projection, drive and limits are activated by setting the appropriate flags on the joint. + + @see PxRevoluteJointCreate() PxJoint +*/ +class PxSphericalJoint : public PxJoint +{ +public: + + /** + \brief Set the limit cone. + + If enabled, the limit cone will constrain the angular movement of the joint to lie + within an elliptical cone. + + \return the limit cone + + @see PxJointLimitCone setLimit() + */ + virtual PxJointLimitCone getLimitCone() const = 0; + + /** + \brief Get the limit cone. + + \param[in] limit the limit cone + + @see PxJointLimitCone getLimit() + */ + virtual void setLimitCone(const PxJointLimitCone& limit) = 0; + + /** + \brief get the swing angle of the joint from the Y axis + */ + virtual PxReal getSwingYAngle() const = 0; + + /** + \brief get the swing angle of the joint from the Z axis + */ + virtual PxReal getSwingZAngle() const = 0; + + /** + \brief Set the flags specific to the Spherical Joint. + + Default PxSphericalJointFlags(0) + + \param[in] flags The joint flags. + + @see PxSphericalJointFlag setFlag() getFlags() + */ + virtual void setSphericalJointFlags(PxSphericalJointFlags flags) = 0; + + /** + \brief Set a single flag specific to a Spherical Joint to true or false. + + \param[in] flag The flag to set or clear. + \param[in] value the value to which to set the flag + + @see PxSphericalJointFlag, getFlags() setFlags() + */ + virtual void setSphericalJointFlag(PxSphericalJointFlag::Enum flag, bool value) = 0; + + /** + \brief Get the flags specific to the Spherical Joint. + + \return the joint flags + + @see PxSphericalJoint::flags, PxSphericalJointFlag setFlag() setFlags() + */ + virtual PxSphericalJointFlags getSphericalJointFlags() const = 0; + + /** + \brief Set the linear tolerance threshold for projection. Projection is enabled if PxConstraintFlag::ePROJECTION + is set for the joint. + + If the joint separates by more than this distance along its locked degrees of freedom, the solver + will move the bodies to close the distance. + + Setting a very small tolerance may result in simulation jitter or other artifacts. + + Sometimes it is not possible to project (for example when the joints form a cycle). + + Range: [0, PX_MAX_F32)
+ Default: 1e10f + + \param[in] tolerance the linear tolerance threshold + + @see getProjectionLinearTolerance() PxJoint::setConstraintFlags() PxConstraintFlag::ePROJECTION + */ + virtual void setProjectionLinearTolerance(PxReal tolerance) = 0; + + /** + \brief Get the linear tolerance threshold for projection. + + \return the linear tolerance threshold + + @see setProjectionLinearTolerance() + */ + virtual PxReal getProjectionLinearTolerance() const = 0; + + /** + \brief Returns string name of PxSphericalJoint, used for serialization + */ + virtual const char* getConcreteTypeName() const { return "PxSphericalJoint"; } + +protected: + + //serialization + + /** + \brief Constructor + */ + PX_INLINE PxSphericalJoint(PxType concreteType, PxBaseFlags baseFlags) : PxJoint(concreteType, baseFlags) {} + + /** + \brief Deserialization constructor + */ + PX_INLINE PxSphericalJoint(PxBaseFlags baseFlags) : PxJoint(baseFlags) {} + + /** + \brief Returns whether a given type name matches with the type of this instance + */ + virtual bool isKindOf(const char* name) const { return !::strcmp("PxSphericalJoint", name) || PxJoint::isKindOf(name); } + + //~serialization +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/extensions/PxStringTableExt.h b/sources/PhysX/PhysX/include/extensions/PxStringTableExt.h new file mode 100644 index 00000000..a40f1d33 --- /dev/null +++ b/sources/PhysX/PhysX/include/extensions/PxStringTableExt.h @@ -0,0 +1,57 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_STRING_TABLE_EXT_H +#define PX_STRING_TABLE_EXT_H +#include "foundation/Px.h" +#include "common/PxStringTable.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief a factory class for creating PxStringTable with a specific allocator. + +@see PxStringTable +*/ + +class PxStringTableExt +{ +public: + static PxStringTable& createStringTable( physx::PxAllocatorCallback& inAllocator ); +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +#endif diff --git a/sources/PhysX/PhysX/include/extensions/PxTriangleMeshExt.h b/sources/PhysX/PhysX/include/extensions/PxTriangleMeshExt.h new file mode 100644 index 00000000..8bee28db --- /dev/null +++ b/sources/PhysX/PhysX/include/extensions/PxTriangleMeshExt.h @@ -0,0 +1,188 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_EXTENSIONS_TRIANGLE_MESH_H +#define PX_PHYSICS_EXTENSIONS_TRIANGLE_MESH_H +/** \addtogroup extensions + @{ +*/ + +#include "PxPhysXConfig.h" +#include "common/PxPhysXCommonConfig.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxGeometry; +class PxTriangleMeshGeometry; +class PxHeightFieldGeometry; + + /** + \brief Utility class to find mesh triangles touched by a specified geometry object. + + This class is a helper calling PxMeshQuery::findOverlapTriangleMesh or PxMeshQuery::findOverlapHeightField under the hood, + while taking care of necessary memory management issues. + + PxMeshQuery::findOverlapTriangleMesh and PxMeshQuery::findOverlapHeightField are the "raw" functions operating on user-provided fixed-size + buffers. These functions abort with an error code in case of buffer overflow. PxMeshOverlapUtil is a convenient helper function checking + this error code, and resizing buffers appropriately, until the desired call succeeds. + + Returned triangle indices are stored within the class, and can be used with PxMeshQuery::getTriangle() to retrieve the triangle properties. + */ + class PxMeshOverlapUtil + { + public: + PxMeshOverlapUtil(); + ~PxMeshOverlapUtil(); + /** + \brief Find the mesh triangles which touch the specified geometry object. + + \param[in] geom The geometry object to test for mesh triangle overlaps. Supported geometries are #PxSphereGeometry, #PxCapsuleGeometry and #PxBoxGeometry + \param[in] geomPose Pose of the geometry object + \param[in] meshGeom The triangle mesh geometry to check overlap against + \param[in] meshPose Pose of the triangle mesh + \return Number of overlaps found. Triangle indices can then be accessed through the #getResults() function. + + @see PxGeometry PxTransform PxTriangleMeshGeometry PxMeshQuery::findOverlapTriangleMesh + */ + PxU32 findOverlap(const PxGeometry& geom, const PxTransform& geomPose, const PxTriangleMeshGeometry& meshGeom, const PxTransform& meshPose); + + /** + \brief Find the height field triangles which touch the specified geometry object. + + \param[in] geom The geometry object to test for height field overlaps. Supported geometries are #PxSphereGeometry, #PxCapsuleGeometry and #PxBoxGeometry. The sphere and capsule queries are currently conservative estimates. + \param[in] geomPose Pose of the geometry object + \param[in] hfGeom The height field geometry to check overlap against + \param[in] hfPose Pose of the height field + \return Number of overlaps found. Triangle indices can then be accessed through the #getResults() function. + + @see PxGeometry PxTransform PxHeightFieldGeometry PxMeshQuery::findOverlapHeightField + */ + PxU32 findOverlap(const PxGeometry& geom, const PxTransform& geomPose, const PxHeightFieldGeometry& hfGeom, const PxTransform& hfPose); + + /** + \brief Retrieves array of triangle indices after a findOverlap call. + \return Indices of touched triangles + */ + PX_FORCE_INLINE const PxU32* getResults() const { return mResultsMemory; } + + /** + \brief Retrieves number of triangle indices after a findOverlap call. + \return Number of touched triangles + */ + PX_FORCE_INLINE PxU32 getNbResults() const { return mNbResults; } + + private: + PxU32* mResultsMemory; + PxU32 mResults[256]; + PxU32 mNbResults; + PxU32 mMaxNbResults; + }; + + /** + \brief Computes an approximate minimum translational distance (MTD) between a geometry object and a mesh. + + This iterative function computes an approximate vector that can be used to depenetrate a geom object + from a triangle mesh. Returned depenetration vector should be applied to 'geom', to get out of the mesh. + + The function works best when the amount of overlap between the geom object and the mesh is small. If the + geom object's center goes inside the mesh, backface culling usually kicks in, no overlap is detected, + and the function does not compute an MTD vector. + + The function early exits if no overlap is detected after a depenetration attempt. This means that if + maxIter = N, the code will attempt at most N iterations but it might exit earlier if depenetration has + been successful. Usually N = 4 gives good results. + + \param[out] direction Computed MTD unit direction + \param[out] depth Penetration depth. Always positive or zero. + \param[in] geom The geometry object + \param[in] geomPose Pose for the geometry object + \param[in] meshGeom The mesh geometry + \param[in] meshPose Pose for the mesh + \param[in] maxIter Max number of iterations before returning. + \param[out] usedIter Number of depenetrations attempts performed during the call. Will not be returned if the pointer is NULL. + + \return True if the MTD has successfully been computed, i.e. if objects do overlap. + + @see PxGeometry PxTransform PxTriangleMeshGeometry + */ + bool PxComputeTriangleMeshPenetration(PxVec3& direction, + PxReal& depth, + const PxGeometry& geom, + const PxTransform& geomPose, + const PxTriangleMeshGeometry& meshGeom, + const PxTransform& meshPose, + PxU32 maxIter, + PxU32* usedIter = NULL); + + /** + \brief Computes an approximate minimum translational distance (MTD) between a geometry object and a heightfield. + + This iterative function computes an approximate vector that can be used to depenetrate a geom object + from a heightfield. Returned depenetration vector should be applied to 'geom', to get out of the heightfield. + + The function works best when the amount of overlap between the geom object and the mesh is small. If the + geom object's center goes inside the heightfield, backface culling usually kicks in, no overlap is detected, + and the function does not compute an MTD vector. + + The function early exits if no overlap is detected after a depenetration attempt. This means that if + maxIter = N, the code will attempt at most N iterations but it might exit earlier if depenetration has + been successful. Usually N = 4 gives good results. + + \param[out] direction Computed MTD unit direction + \param[out] depth Penetration depth. Always positive or zero. + \param[in] geom The geometry object + \param[in] geomPose Pose for the geometry object + \param[in] heightFieldGeom The heightfield geometry + \param[in] heightFieldPose Pose for the heightfield + \param[in] maxIter Max number of iterations before returning. + \param[out] usedIter Number of depenetrations attempts performed during the call. Will not be returned if the pointer is NULL. + + \return True if the MTD has successfully been computed, i.e. if objects do overlap. + + @see PxGeometry PxTransform PxHeightFieldGeometry + */ + bool PxComputeHeightFieldPenetration(PxVec3& direction, + PxReal& depth, + const PxGeometry& geom, + const PxTransform& geomPose, + const PxHeightFieldGeometry& heightFieldGeom, + const PxTransform& heightFieldPose, + PxU32 maxIter, + PxU32* usedIter = NULL); + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/filebuf/PxFileBuf.h b/sources/PhysX/PhysX/include/filebuf/PxFileBuf.h new file mode 100644 index 00000000..9431fc36 --- /dev/null +++ b/sources/PhysX/PhysX/include/filebuf/PxFileBuf.h @@ -0,0 +1,339 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PSFILEBUFFER_PXFILEBUF_H +#define PSFILEBUFFER_PXFILEBUF_H + +#include "foundation/PxSimpleTypes.h" + +/** \addtogroup foundation + @{ +*/ + +#if !PX_DOXYGEN +namespace physx +{ + +namespace general_PxIOStream2 +{ +#endif + +PX_PUSH_PACK_DEFAULT + +/** +\brief Callback class for data serialization. + +The user needs to supply an PxFileBuf implementation to a number of methods to allow the SDK to read or write +chunks of binary data. This allows flexibility for the source/destination of the data. For example the PxFileBuf +could store data in a file, memory buffer or custom file format. + +\note It is the users responsibility to ensure that the data is written to the appropriate offset. + +*/ +class PxFileBuf +{ +public: + + enum EndianMode + { + ENDIAN_NONE = 0, // do no conversion for endian mode + ENDIAN_BIG = 1, // always read/write data as natively big endian (Power PC, etc.) + ENDIAN_LITTLE = 2 // always read/write data as natively little endian (Intel, etc.) Default Behavior! + }; + + PxFileBuf(EndianMode mode=ENDIAN_LITTLE) + { + setEndianMode(mode); + } + + virtual ~PxFileBuf(void) + { + + } + + /** + \brief Declares a constant to seek to the end of the stream. + * + * Does not support streams longer than 32 bits + */ + static const uint32_t STREAM_SEEK_END=0xFFFFFFFF; + + enum OpenMode + { + OPEN_FILE_NOT_FOUND, + OPEN_READ_ONLY, // open file buffer stream for read only access + OPEN_WRITE_ONLY, // open file buffer stream for write only access + OPEN_READ_WRITE_NEW, // open a new file for both read/write access + OPEN_READ_WRITE_EXISTING // open an existing file for both read/write access + }; + + virtual OpenMode getOpenMode(void) const = 0; + + bool isOpen(void) const + { + return getOpenMode()!=OPEN_FILE_NOT_FOUND; + } + + enum SeekType + { + SEEKABLE_NO = 0, + SEEKABLE_READ = 0x1, + SEEKABLE_WRITE = 0x2, + SEEKABLE_READWRITE = 0x3 + }; + + virtual SeekType isSeekable(void) const = 0; + + void setEndianMode(EndianMode e) + { + mEndianMode = e; + if ( (e==ENDIAN_BIG && !isBigEndian() ) || + (e==ENDIAN_LITTLE && isBigEndian() ) ) + { + mEndianSwap = true; + } + else + { + mEndianSwap = false; + } + } + + EndianMode getEndianMode(void) const + { + return mEndianMode; + } + + virtual uint32_t getFileLength(void) const = 0; + + /** + \brief Seeks the stream to a particular location for reading + * + * If the location passed exceeds the length of the stream, then it will seek to the end. + * Returns the location it ended up at (useful if you seek to the end) to get the file position + */ + virtual uint32_t seekRead(uint32_t loc) = 0; + + /** + \brief Seeks the stream to a particular location for writing + * + * If the location passed exceeds the length of the stream, then it will seek to the end. + * Returns the location it ended up at (useful if you seek to the end) to get the file position + */ + virtual uint32_t seekWrite(uint32_t loc) = 0; + + /** + \brief Reads from the stream into a buffer. + + \param[out] mem The buffer to read the stream into. + \param[in] len The number of bytes to stream into the buffer + + \return Returns the actual number of bytes read. If not equal to the length requested, then reached end of stream. + */ + virtual uint32_t read(void *mem,uint32_t len) = 0; + + + /** + \brief Reads from the stream into a buffer but does not advance the read location. + + \param[out] mem The buffer to read the stream into. + \param[in] len The number of bytes to stream into the buffer + + \return Returns the actual number of bytes read. If not equal to the length requested, then reached end of stream. + */ + virtual uint32_t peek(void *mem,uint32_t len) = 0; + + /** + \brief Writes a buffer of memory to the stream + + \param[in] mem The address of a buffer of memory to send to the stream. + \param[in] len The number of bytes to send to the stream. + + \return Returns the actual number of bytes sent to the stream. If not equal to the length specific, then the stream is full or unable to write for some reason. + */ + virtual uint32_t write(const void *mem,uint32_t len) = 0; + + /** + \brief Reports the current stream location read aqccess. + + \return Returns the current stream read location. + */ + virtual uint32_t tellRead(void) const = 0; + + /** + \brief Reports the current stream location for write access. + + \return Returns the current stream write location. + */ + virtual uint32_t tellWrite(void) const = 0; + + /** + \brief Causes any temporarily cached data to be flushed to the stream. + */ + virtual void flush(void) = 0; + + /** + \brief Close the stream. + */ + virtual void close(void) {} + + void release(void) + { + delete this; + } + + static PX_INLINE bool isBigEndian() + { + int32_t i = 1; + return *(reinterpret_cast(&i))==0; + } + + PX_INLINE void swap2Bytes(void* _data) const + { + char *data = static_cast(_data); + char one_byte; + one_byte = data[0]; data[0] = data[1]; data[1] = one_byte; + } + + PX_INLINE void swap4Bytes(void* _data) const + { + char *data = static_cast(_data); + char one_byte; + one_byte = data[0]; data[0] = data[3]; data[3] = one_byte; + one_byte = data[1]; data[1] = data[2]; data[2] = one_byte; + } + + PX_INLINE void swap8Bytes(void *_data) const + { + char *data = static_cast(_data); + char one_byte; + one_byte = data[0]; data[0] = data[7]; data[7] = one_byte; + one_byte = data[1]; data[1] = data[6]; data[6] = one_byte; + one_byte = data[2]; data[2] = data[5]; data[5] = one_byte; + one_byte = data[3]; data[3] = data[4]; data[4] = one_byte; + } + + + PX_INLINE void storeDword(uint32_t v) + { + if ( mEndianSwap ) + swap4Bytes(&v); + + write(&v,sizeof(v)); + } + + PX_INLINE void storeFloat(float v) + { + if ( mEndianSwap ) + swap4Bytes(&v); + write(&v,sizeof(v)); + } + + PX_INLINE void storeDouble(double v) + { + if ( mEndianSwap ) + swap8Bytes(&v); + write(&v,sizeof(v)); + } + + PX_INLINE void storeByte(uint8_t b) + { + write(&b,sizeof(b)); + } + + PX_INLINE void storeWord(uint16_t w) + { + if ( mEndianSwap ) + swap2Bytes(&w); + write(&w,sizeof(w)); + } + + uint8_t readByte(void) + { + uint8_t v=0; + read(&v,sizeof(v)); + return v; + } + + uint16_t readWord(void) + { + uint16_t v=0; + read(&v,sizeof(v)); + if ( mEndianSwap ) + swap2Bytes(&v); + return v; + } + + uint32_t readDword(void) + { + uint32_t v=0; + read(&v,sizeof(v)); + if ( mEndianSwap ) + swap4Bytes(&v); + return v; + } + + float readFloat(void) + { + float v=0; + read(&v,sizeof(v)); + if ( mEndianSwap ) + swap4Bytes(&v); + return v; + } + + double readDouble(void) + { + double v=0; + read(&v,sizeof(v)); + if ( mEndianSwap ) + swap8Bytes(&v); + return v; + } + +private: + bool mEndianSwap; // whether or not the endian should be swapped on the current platform + EndianMode mEndianMode; // the current endian mode behavior for the stream +}; + +PX_POP_PACK + +#if !PX_DOXYGEN +} // end of namespace + +using namespace general_PxIOStream2; + +namespace general_PxIOStream = general_PxIOStream2; + +} // end of namespace +#endif + +/** @} */ + +#endif // PSFILEBUFFER_PXFILEBUF_H diff --git a/sources/PhysX/PhysX/include/foundation/PxAssert.h b/sources/PhysX/PhysX/include/foundation/PxAssert.h new file mode 100644 index 00000000..88309d53 --- /dev/null +++ b/sources/PhysX/PhysX/include/foundation/PxAssert.h @@ -0,0 +1,98 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_FOUNDATION_PX_ASSERT_H +#define PX_FOUNDATION_PX_ASSERT_H + +#include "foundation/PxFoundationConfig.h" +#include "foundation/Px.h" + +/** \addtogroup foundation + @{ +*/ + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/* Base class to handle assert failures */ +class PX_DEPRECATED PxAssertHandler +{ + public: + virtual ~PxAssertHandler() + { + } + virtual void operator()(const char* exp, const char* file, int line, bool& ignore) = 0; +}; + +PX_FOUNDATION_API PX_DEPRECATED PxAssertHandler& PxGetAssertHandler(); +PX_FOUNDATION_API PX_DEPRECATED void PxSetAssertHandler(PxAssertHandler& handler); + +#if !PX_ENABLE_ASSERTS + #define PX_ASSERT(exp) ((void)0) + #define PX_ALWAYS_ASSERT_MESSAGE(exp) ((void)0) + #define PX_ASSERT_WITH_MESSAGE(condition, message) ((void)0) +#else +#if PX_VC + #define PX_CODE_ANALYSIS_ASSUME(exp) \ + __analysis_assume(!!(exp)) // This macro will be used to get rid of analysis warning messages if a PX_ASSERT is used + // to "guard" illegal mem access, for example. +#else + #define PX_CODE_ANALYSIS_ASSUME(exp) +#endif + #define PX_ASSERT(exp) \ + { \ + static bool _ignore = false; \ + ((void)((!!(exp)) || (!_ignore && (physx::PxGetAssertHandler()(#exp, __FILE__, __LINE__, _ignore), false)))); \ + PX_CODE_ANALYSIS_ASSUME(exp); \ + } + #define PX_ALWAYS_ASSERT_MESSAGE(exp) \ + { \ + static bool _ignore = false; \ + if(!_ignore) \ + physx::PxGetAssertHandler()(exp, __FILE__, __LINE__, _ignore); \ + } + #define PX_ASSERT_WITH_MESSAGE(exp, message) \ + { \ + static bool _ignore = false; \ + ((void)((!!(exp)) || (!_ignore && (physx::PxGetAssertHandler()(message, __FILE__, __LINE__, _ignore), false)))); \ + PX_CODE_ANALYSIS_ASSUME(exp); \ + } +#endif // !PX_ENABLE_ASSERTS + +#define PX_ALWAYS_ASSERT() PX_ASSERT(0) + +#if !PX_DOXYGEN +} // namespace physx +#endif + + +/** @} */ +#endif // PX_FOUNDATION_PX_ASSERT_H diff --git a/sources/PhysX/PhysX/include/foundation/PxFoundationConfig.h b/sources/PhysX/PhysX/include/foundation/PxFoundationConfig.h new file mode 100644 index 00000000..a2e74ece --- /dev/null +++ b/sources/PhysX/PhysX/include/foundation/PxFoundationConfig.h @@ -0,0 +1,57 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_FOUNDATION_PX_FOUNDATION_CONFIG_H +#define PX_FOUNDATION_PX_FOUNDATION_CONFIG_H + +#include "foundation/PxPreprocessor.h" + +/** \addtogroup foundation + @{ +*/ + +#if defined PX_PHYSX_STATIC_LIB + #define PX_FOUNDATION_API +#else + #if (PX_WINDOWS_FAMILY || PX_XBOXONE || PX_PS4) && !defined(__CUDACC__) + #if defined PX_PHYSX_FOUNDATION_EXPORTS + #define PX_FOUNDATION_API __declspec(dllexport) + #else + #define PX_FOUNDATION_API __declspec(dllimport) + #endif + #elif PX_UNIX_FAMILY + #define PX_FOUNDATION_API PX_UNIX_EXPORT + #else + #define PX_FOUNDATION_API + #endif +#endif + + +/** @} */ +#endif // PX_FOUNDATION_PX_ASSERT_H diff --git a/sources/PhysX/PhysX/include/foundation/PxMathUtils.h b/sources/PhysX/PhysX/include/foundation/PxMathUtils.h new file mode 100644 index 00000000..445439c0 --- /dev/null +++ b/sources/PhysX/PhysX/include/foundation/PxMathUtils.h @@ -0,0 +1,74 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PXFOUNDATION_PXMATHUTILS_H +#define PXFOUNDATION_PXMATHUTILS_H + +/** \addtogroup common + @{ +*/ + +#include "foundation/Px.h" +#include "foundation/PxFoundationConfig.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief finds the shortest rotation between two vectors. + +\param[in] from the vector to start from +\param[in] target the vector to rotate to +\return a rotation about an axis normal to the two vectors which takes one to the other via the shortest path +*/ + +PX_FOUNDATION_API PxQuat PxShortestRotation(const PxVec3& from, const PxVec3& target); + +/* \brief diagonalizes a 3x3 symmetric matrix y + +The returned matrix satisfies M = R * D * R', where R is the rotation matrix for the output quaternion, R' its +transpose, and D the diagonal matrix + +If the matrix is not symmetric, the result is undefined. + +\param[in] m the matrix to diagonalize +\param[out] axes a quaternion rotation which diagonalizes the matrix +\return the vector diagonal of the diagonalized matrix. +*/ + +PX_FOUNDATION_API PxVec3 PxDiagonalize(const PxMat33& m, PxQuat& axes); + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/geometry/PxBVHStructure.h b/sources/PhysX/PhysX/include/geometry/PxBVHStructure.h new file mode 100644 index 00000000..1ff9d3f2 --- /dev/null +++ b/sources/PhysX/PhysX/include/geometry/PxBVHStructure.h @@ -0,0 +1,138 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_BVH_STRUCTURE +#define PX_PHYSICS_BVH_STRUCTURE +/** \addtogroup geomutils +@{ +*/ + +#include "common/PxBase.h" +#include "foundation/PxTransform.h" +#include "foundation/PxBounds3.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief Class representing the bounding volume hierarchy structure. + +PxBVHStructure can be provided to PxScene::addActor. In this case the scene query +pruning structure inside PhysX SDK will store/update one bound per actor. +The scene queries against such an actor will query actor bounds and then +make a local space query against the provided BVH structure, which is in +actor's local space. + +@see PxScene::addActor +*/ +class PxBVHStructure: public PxBase +{ +public: + + /** + \brief Raycast test against a BVH structure. + + \param[in] origin The origin of the ray. + \param[in] unitDir Normalized direction of the ray. + \param[in] maxDist Maximum ray length, has to be in the [0, inf) range + \param[in] maxHits Max number of returned hits = size of 'rayHits' buffer + \param[out] rayHits Raycast hits information, bounds indices + \return Number of hits + */ + virtual PxU32 raycast(const PxVec3& origin, + const PxVec3& unitDir, + PxReal maxDist, + PxU32 maxHits, + PxU32* PX_RESTRICT rayHits) const = 0; + + /** + \brief Sweep test against a BVH structure. + + \param[in] aabb The axis aligned bounding box to sweep + \param[in] unitDir Normalized direction of the sweep. + \param[in] maxDist Maximum sweep length, has to be in the [0, inf) range + \param[in] maxHits Max number of returned hits = size of 'sweepHits' buffer + \param[out] sweepHits Sweep hits information, bounds indices + \return Number of hits + */ + virtual PxU32 sweep(const PxBounds3& aabb, + const PxVec3& unitDir, + PxReal maxDist, + PxU32 maxHits, + PxU32* PX_RESTRICT sweepHits) const = 0; + + /** + \brief AABB overlap test against a BVH structure. + + \param[in] aabb The axis aligned bounding box + \param[in] maxHits Max number of returned hits = size of 'overlapHits' buffer + \param[out] overlapHits Overlap hits information, bounds indices + \return Number of hits + */ + virtual PxU32 overlap(const PxBounds3& aabb, + PxU32 maxHits, + PxU32* PX_RESTRICT overlapHits) const = 0; + + /** + \brief Retrieve the bounds in the BVH. + + @see PxBounds3 + */ + virtual const PxBounds3* getBounds() const = 0; + + /** + \brief Returns the number of bounds in the BVH. + + You can use #getBounds() to retrieve the bounds. + + \return Number of bounds in the BVH. + + */ + virtual PxU32 getNbBounds() const = 0; + + virtual const char* getConcreteTypeName() const { return "PxBVHStructure"; } +protected: + PX_INLINE PxBVHStructure(PxType concreteType, PxBaseFlags baseFlags) : PxBase(concreteType, baseFlags) {} + PX_INLINE PxBVHStructure(PxBaseFlags baseFlags) : PxBase(baseFlags) {} + virtual ~PxBVHStructure() {} + + virtual bool isKindOf(const char* name) const { return !::strcmp("PxBVHStructure", name) || PxBase::isKindOf(name); } + +}; + + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/geometry/PxBoxGeometry.h b/sources/PhysX/PhysX/include/geometry/PxBoxGeometry.h new file mode 100644 index 00000000..0c24790e --- /dev/null +++ b/sources/PhysX/PhysX/include/geometry/PxBoxGeometry.h @@ -0,0 +1,109 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX_BOX_GEOMETRY +#define PX_PHYSICS_NX_BOX_GEOMETRY +/** \addtogroup geomutils +@{ +*/ +#include "geometry/PxGeometry.h" +#include "foundation/PxVec3.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief Class representing the geometry of a box. + +The geometry of a box can be fully specified by its half extents. This is the half of its width, height, and depth. +\note The scaling of the box is expected to be baked into these values, there is no additional scaling parameter. +*/ +class PxBoxGeometry : public PxGeometry +{ +public: + /** + \brief Default constructor, initializes to a box with zero dimensions. + */ + PX_INLINE PxBoxGeometry() : PxGeometry(PxGeometryType::eBOX), halfExtents(0,0,0) {} + + /** + \brief Constructor to initialize half extents from scalar parameters. + \param hx Initial half extents' x component. + \param hy Initial half extents' y component. + \param hz Initial half extents' z component. + */ + PX_INLINE PxBoxGeometry(PxReal hx, PxReal hy, PxReal hz) : PxGeometry(PxGeometryType::eBOX), halfExtents(hx, hy, hz) {} + + /** + \brief Constructor to initialize half extents from vector parameter. + \param halfExtents_ Initial half extents. + */ + PX_INLINE PxBoxGeometry(PxVec3 halfExtents_) : PxGeometry(PxGeometryType::eBOX), halfExtents(halfExtents_) {} + + /** + \brief Returns true if the geometry is valid. + + \return True if the current settings are valid + + \note A valid box has a positive extent in each direction (halfExtents.x > 0, halfExtents.y > 0, halfExtents.z > 0). + It is illegal to call PxRigidActor::createShape and PxPhysics::createShape with a box that has zero extent in any direction. + + @see PxRigidActor::createShape, PxPhysics::createShape + */ + PX_INLINE bool isValid() const; + +public: + /** + \brief Half of the width, height, and depth of the box. + */ + PxVec3 halfExtents; +}; + + +PX_INLINE bool PxBoxGeometry::isValid() const +{ + if (mType != PxGeometryType::eBOX) + return false; + if (!halfExtents.isFinite()) + return false; + if (halfExtents.x <= 0.0f || halfExtents.y <= 0.0f || halfExtents.z <= 0.0f) + return false; + + return true; +} + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/geometry/PxCapsuleGeometry.h b/sources/PhysX/PhysX/include/geometry/PxCapsuleGeometry.h new file mode 100644 index 00000000..33774e1c --- /dev/null +++ b/sources/PhysX/PhysX/include/geometry/PxCapsuleGeometry.h @@ -0,0 +1,122 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX_CAPSULE_GEOMETRY +#define PX_PHYSICS_NX_CAPSULE_GEOMETRY +/** \addtogroup geomutils +@{ +*/ +#include "geometry/PxGeometry.h" +#include "foundation/PxFoundationConfig.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief Class representing the geometry of a capsule. + +Capsules are shaped as the union of a cylinder of length 2 * halfHeight and with the +given radius centered at the origin and extending along the x axis, and two hemispherical ends. +\note The scaling of the capsule is expected to be baked into these values, there is no additional scaling parameter. + +The function PxTransformFromSegment is a helper for generating an appropriate transform for the capsule from the capsule's interior line segment. + +@see PxTransformFromSegment +*/ +class PxCapsuleGeometry : public PxGeometry +{ +public: + /** + \brief Default constructor, initializes to a capsule with zero height and radius. + */ + PX_INLINE PxCapsuleGeometry() : PxGeometry(PxGeometryType::eCAPSULE), radius(0), halfHeight(0) {} + + /** + \brief Constructor, initializes to a capsule with passed radius and half height. + */ + PX_INLINE PxCapsuleGeometry(PxReal radius_, PxReal halfHeight_) : PxGeometry(PxGeometryType::eCAPSULE), radius(radius_), halfHeight(halfHeight_) {} + + /** + \brief Returns true if the geometry is valid. + + \return True if the current settings are valid. + + \note A valid capsule has radius > 0, halfHeight > 0. + It is illegal to call PxRigidActor::createShape and PxPhysics::createShape with a capsule that has zero radius or height. + + @see PxRigidActor::createShape, PxPhysics::createShape + */ + PX_INLINE bool isValid() const; + +public: + /** + \brief The radius of the capsule. + */ + PxReal radius; + + /** + \brief half of the capsule's height, measured between the centers of the hemispherical ends. + */ + PxReal halfHeight; +}; + + +PX_INLINE bool PxCapsuleGeometry::isValid() const +{ + if (mType != PxGeometryType::eCAPSULE) + return false; + if (!PxIsFinite(radius) || !PxIsFinite(halfHeight)) + return false; + if (radius <= 0.0f || halfHeight <= 0.0f) + return false; + + return true; +} + + +/** \brief creates a transform from the endpoints of a segment, suitable for an actor transform for a PxCapsuleGeometry + +\param[in] p0 one end of major axis of the capsule +\param[in] p1 the other end of the axis of the capsule +\param[out] halfHeight the halfHeight of the capsule. This parameter is optional. +\return A PxTransform which will transform the vector (1,0,0) to the capsule axis shrunk by the halfHeight +*/ + +PX_FOUNDATION_API PxTransform PxTransformFromSegment(const PxVec3& p0, const PxVec3& p1, PxReal* halfHeight = NULL); + + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/geometry/PxConvexMesh.h b/sources/PhysX/PhysX/include/geometry/PxConvexMesh.h new file mode 100644 index 00000000..80434ed7 --- /dev/null +++ b/sources/PhysX/PhysX/include/geometry/PxConvexMesh.h @@ -0,0 +1,197 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_GEOMUTILS_NX_CONVEXMESH +#define PX_PHYSICS_GEOMUTILS_NX_CONVEXMESH +/** \addtogroup geomutils + @{ +*/ + +#include "foundation/Px.h" +#include "common/PxBase.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief Polygon data + +Plane format: (mPlane[0],mPlane[1],mPlane[2]).dot(x) + mPlane[3] = 0 +With the normal outward-facing from the hull. +*/ +struct PxHullPolygon +{ + PxReal mPlane[4]; //!< Plane equation for this polygon + PxU16 mNbVerts; //!< Number of vertices/edges in the polygon + PxU16 mIndexBase; //!< Offset in index buffer +}; + +/** +\brief A convex mesh. + +Internally represented as a list of convex polygons. The number +of polygons is limited to 256. + +To avoid duplicating data when you have several instances of a particular +mesh positioned differently, you do not use this class to represent a +convex object directly. Instead, you create an instance of this mesh via +the PxConvexMeshGeometry and PxShape classes. + +

Creation

+ +To create an instance of this class call PxPhysics::createConvexMesh(), +and PxConvexMesh::release() to delete it. This is only possible +once you have released all of its #PxShape instances. + +

Visualizations:

+\li #PxVisualizationParameter::eCOLLISION_AABBS +\li #PxVisualizationParameter::eCOLLISION_SHAPES +\li #PxVisualizationParameter::eCOLLISION_AXES +\li #PxVisualizationParameter::eCOLLISION_FNORMALS +\li #PxVisualizationParameter::eCOLLISION_EDGES + +@see PxConvexMeshDesc PxPhysics.createConvexMesh() +*/ +class PxConvexMesh : public PxBase +{ +public: + + /** + \brief Returns the number of vertices. + \return Number of vertices. + @see getVertices() + */ + PX_PHYSX_COMMON_API virtual PxU32 getNbVertices() const = 0; + + /** + \brief Returns the vertices. + \return Array of vertices. + @see getNbVertices() + */ + PX_PHYSX_COMMON_API virtual const PxVec3* getVertices() const = 0; + + /** + \brief Returns the index buffer. + \return Index buffer. + @see getNbPolygons() getPolygonData() + */ + PX_PHYSX_COMMON_API virtual const PxU8* getIndexBuffer() const = 0; + + /** + \brief Returns the number of polygons. + \return Number of polygons. + @see getIndexBuffer() getPolygonData() + */ + PX_PHYSX_COMMON_API virtual PxU32 getNbPolygons() const = 0; + + /** + \brief Returns the polygon data. + \param[in] index Polygon index in [0 ; getNbPolygons()[. + \param[out] data Polygon data. + \return True if success. + @see getIndexBuffer() getNbPolygons() + */ + PX_PHYSX_COMMON_API virtual bool getPolygonData(PxU32 index, PxHullPolygon& data) const = 0; + + /** + \brief Decrements the reference count of a convex mesh and releases it if the new reference count is zero. + + @see PxPhysics.createConvexMesh() PxConvexMeshGeometry PxShape + */ + PX_PHYSX_COMMON_API virtual void release() = 0; + + /** + \brief Returns the reference count of a convex mesh. + + At creation, the reference count of the convex mesh is 1. Every shape referencing this convex mesh increments the + count by 1. When the reference count reaches 0, and only then, the convex mesh gets destroyed automatically. + + \return the current reference count. + */ + PX_PHYSX_COMMON_API virtual PxU32 getReferenceCount() const = 0; + + /** + \brief Acquires a counted reference to a convex mesh. + + This method increases the reference count of the convex mesh by 1. Decrement the reference count by calling release() + */ + PX_PHYSX_COMMON_API virtual void acquireReference() = 0; + + /** + \brief Returns the mass properties of the mesh assuming unit density. + + The following relationship holds between mass and volume: + + mass = volume * density + + The mass of a unit density mesh is equal to its volume, so this function returns the volume of the mesh. + + Similarly, to obtain the localInertia of an identically shaped object with a uniform density of d, simply multiply the + localInertia of the unit density mesh by d. + + \param[out] mass The mass of the mesh assuming unit density. + \param[out] localInertia The inertia tensor in mesh local space assuming unit density. + \param[out] localCenterOfMass Position of center of mass (or centroid) in mesh local space. + */ + PX_PHYSX_COMMON_API virtual void getMassInformation(PxReal& mass, PxMat33& localInertia, PxVec3& localCenterOfMass) const = 0; + + /** + \brief Returns the local-space (vertex space) AABB from the convex mesh. + + \return local-space bounds + */ + PX_PHYSX_COMMON_API virtual PxBounds3 getLocalBounds() const = 0; + + PX_PHYSX_COMMON_API virtual const char* getConcreteTypeName() const { return "PxConvexMesh"; } + + /** + \brief This method decides whether a convex mesh is gpu compatible. If the total number of vertices are more than 64 or any number of vertices in a polygon is more than 32, or + convex hull data was not cooked with GPU data enabled during cooking or was loaded from a serialized collection, the convex hull is incompatible with GPU collision detection. Otherwise + it is compatible. + + \return True if the convex hull is gpu compatible + */ + PX_PHYSX_COMMON_API virtual bool isGpuCompatible() const = 0; + +protected: + PX_INLINE PxConvexMesh(PxType concreteType, PxBaseFlags baseFlags) : PxBase(concreteType, baseFlags) {} + PX_INLINE PxConvexMesh(PxBaseFlags baseFlags) : PxBase(baseFlags) {} + PX_PHYSX_COMMON_API virtual ~PxConvexMesh() {} + PX_PHYSX_COMMON_API virtual bool isKindOf(const char* name) const { return !::strcmp("PxConvexMesh", name) || PxBase::isKindOf(name); } +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/geometry/PxConvexMeshGeometry.h b/sources/PhysX/PhysX/include/geometry/PxConvexMeshGeometry.h new file mode 100644 index 00000000..62533749 --- /dev/null +++ b/sources/PhysX/PhysX/include/geometry/PxConvexMeshGeometry.h @@ -0,0 +1,151 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX_CONVEXMESH_GEOMETRY +#define PX_PHYSICS_NX_CONVEXMESH_GEOMETRY +/** \addtogroup geomutils +@{ +*/ +#include "geometry/PxGeometry.h" +#include "geometry/PxMeshScale.h" +#include "common/PxCoreUtilityTypes.h" +#include "geometry/PxConvexMesh.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxConvexMesh; + +/** +\brief Flags controlling the simulated behavior of the convex mesh geometry. + +Used in ::PxConvexMeshGeometryFlags. +*/ +struct PxConvexMeshGeometryFlag +{ + enum Enum + { + eTIGHT_BOUNDS = (1<<0) //!< Use tighter (but more expensive to compute) bounds around the convex geometry. + }; +}; + +/** +\brief collection of set bits defined in PxConvexMeshGeometryFlag. + +@see PxConvexMeshGeometryFlag +*/ +typedef PxFlags PxConvexMeshGeometryFlags; +PX_FLAGS_OPERATORS(PxConvexMeshGeometryFlag::Enum,PxU8) + +/** +\brief Convex mesh geometry class. + +This class unifies a convex mesh object with a scaling transform, and +lets the combined object be used anywhere a PxGeometry is needed. + +The scaling is a transform along arbitrary axes contained in the scale object. +The vertices of the mesh in geometry (or shape) space is the +PxMeshScale::toMat33() transform, multiplied by the vertex space vertices +in the PxConvexMesh object. +*/ +class PxConvexMeshGeometry : public PxGeometry +{ +public: + /** + \brief Default constructor. + + Creates an empty object with a NULL mesh and identity scale. + */ + PX_INLINE PxConvexMeshGeometry() : + PxGeometry (PxGeometryType::eCONVEXMESH), + scale (PxMeshScale(1.0f)), + convexMesh (NULL), + meshFlags (PxConvexMeshGeometryFlag::eTIGHT_BOUNDS) + {} + + /** + \brief Constructor. + \param[in] mesh Mesh pointer. May be NULL, though this will not make the object valid for shape construction. + \param[in] scaling Scale factor. + \param[in] flags Mesh flags. + \ + */ + PX_INLINE PxConvexMeshGeometry( PxConvexMesh* mesh, + const PxMeshScale& scaling = PxMeshScale(), + PxConvexMeshGeometryFlags flags = PxConvexMeshGeometryFlag::eTIGHT_BOUNDS) : + PxGeometry (PxGeometryType::eCONVEXMESH), + scale (scaling), + convexMesh (mesh), + meshFlags (flags) + { + } + + /** + \brief Returns true if the geometry is valid. + + \return True if the current settings are valid for shape creation. + + \note A valid convex mesh has a positive scale value in each direction (scale.x > 0, scale.y > 0, scale.z > 0). + It is illegal to call PxRigidActor::createShape and PxPhysics::createShape with a convex that has zero extent in any direction. + + @see PxRigidActor::createShape, PxPhysics::createShape + */ + PX_INLINE bool isValid() const; + +public: + PxMeshScale scale; //!< The scaling transformation (from vertex space to shape space). + PxConvexMesh* convexMesh; //!< A reference to the convex mesh object. + PxConvexMeshGeometryFlags meshFlags; //!< Mesh flags. + PxPadding<3> paddingFromFlags; //!< padding for mesh flags +}; + + +PX_INLINE bool PxConvexMeshGeometry::isValid() const +{ + if(mType != PxGeometryType::eCONVEXMESH) + return false; + if(!scale.scale.isFinite() || !scale.rotation.isUnit()) + return false; + if(!scale.isValidForConvexMesh()) + return false; + if(!convexMesh) + return false; + + return true; +} + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/geometry/PxGeometry.h b/sources/PhysX/PhysX/include/geometry/PxGeometry.h new file mode 100644 index 00000000..2ef93b94 --- /dev/null +++ b/sources/PhysX/PhysX/include/geometry/PxGeometry.h @@ -0,0 +1,94 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX_GEOMETRY +#define PX_PHYSICS_NX_GEOMETRY +/** \addtogroup geomutils +@{ +*/ + +#include "common/PxPhysXCommonConfig.h" +#include "foundation/PxFlags.h" +#include "foundation/PxMath.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief A geometry type. + +Used to distinguish the type of a ::PxGeometry object. +*/ +struct PxGeometryType +{ + enum Enum + { + eSPHERE, + ePLANE, + eCAPSULE, + eBOX, + eCONVEXMESH, + eTRIANGLEMESH, + eHEIGHTFIELD, + eGEOMETRY_COUNT, //!< internal use only! + eINVALID = -1 //!< internal use only! + }; +}; + +/** +\brief A geometry object. + +A geometry object defines the characteristics of a spatial object, but without any information +about its placement in the world. + +\note This is an abstract class. You cannot create instances directly. Create an instance of one of the derived classes instead. +*/ +class PxGeometry +{ +public: + /** + \brief Returns the type of the geometry. + \return The type of the object. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxGeometryType::Enum getType() const { return mType; } + +protected: + PX_CUDA_CALLABLE PX_FORCE_INLINE PxGeometry(PxGeometryType::Enum type) : mType(type) {} + PxGeometryType::Enum mType; +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/geometry/PxGeometryHelpers.h b/sources/PhysX/PhysX/include/geometry/PxGeometryHelpers.h new file mode 100644 index 00000000..5681a930 --- /dev/null +++ b/sources/PhysX/PhysX/include/geometry/PxGeometryHelpers.h @@ -0,0 +1,214 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_GEOMETRYHELPERS +#define PX_PHYSICS_GEOMETRYHELPERS +/** \addtogroup geomutils +@{ +*/ + +#include "foundation/PxPlane.h" +#include "foundation/PxTransform.h" +#include "foundation/PxUnionCast.h" +#include "common/PxPhysXCommonConfig.h" +#include "geometry/PxGeometry.h" +#include "geometry/PxBoxGeometry.h" +#include "geometry/PxSphereGeometry.h" +#include "geometry/PxCapsuleGeometry.h" +#include "geometry/PxPlaneGeometry.h" +#include "geometry/PxConvexMeshGeometry.h" +#include "geometry/PxHeightFieldGeometry.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief Geometry holder class + +This class contains enough space to hold a value of any PxGeometry subtype. + +Its principal use is as a convenience class to allow geometries to be returned polymorphically +from functions. See PxShape::getGeometry(); +*/ + +PX_ALIGN_PREFIX(4) +class PxGeometryHolder +{ +public: + PX_FORCE_INLINE PxGeometryType::Enum getType() const + { + return any().getType(); + } + + PX_FORCE_INLINE PxGeometry& any() + { + return *PxUnionCast(&bytes.geometry); + } + + PX_FORCE_INLINE const PxGeometry& any() const + { + return *PxUnionCast(&bytes.geometry); + } + + PX_FORCE_INLINE PxSphereGeometry& sphere() + { + return get(); + } + + PX_FORCE_INLINE const PxSphereGeometry& sphere() const + { + return get(); + } + + PX_FORCE_INLINE PxPlaneGeometry& plane() + { + return get(); + } + + PX_FORCE_INLINE const PxPlaneGeometry& plane() const + { + return get(); + } + + PX_FORCE_INLINE PxCapsuleGeometry& capsule() + { + return get(); + } + + PX_FORCE_INLINE const PxCapsuleGeometry& capsule() const + { + return get(); + } + + PX_FORCE_INLINE PxBoxGeometry& box() + { + return get(); + } + + PX_FORCE_INLINE const PxBoxGeometry& box() const + { + return get(); + } + + PX_FORCE_INLINE PxConvexMeshGeometry& convexMesh() + { + return get(); + } + + PX_FORCE_INLINE const PxConvexMeshGeometry& convexMesh() const + { + return get(); + } + + PX_FORCE_INLINE PxTriangleMeshGeometry& triangleMesh() + { + return get(); + } + + PX_FORCE_INLINE const PxTriangleMeshGeometry& triangleMesh() const + { + return get(); + } + + PX_FORCE_INLINE PxHeightFieldGeometry& heightField() + { + return get(); + } + + PX_FORCE_INLINE const PxHeightFieldGeometry& heightField() const + { + return get(); + } + + PX_FORCE_INLINE void storeAny(const PxGeometry& geometry) + { + PX_ASSERT_WITH_MESSAGE( (geometry.getType() >= PxGeometryType::eSPHERE) && + (geometry.getType() < PxGeometryType::eGEOMETRY_COUNT), + "Unexpected GeometryType in PxGeometryHolder::storeAny"); + + switch(geometry.getType()) + { + case PxGeometryType::eSPHERE: put(geometry); break; + case PxGeometryType::ePLANE: put(geometry); break; + case PxGeometryType::eCAPSULE: put(geometry); break; + case PxGeometryType::eBOX: put(geometry); break; + case PxGeometryType::eCONVEXMESH: put(geometry); break; + case PxGeometryType::eTRIANGLEMESH: put(geometry); break; + case PxGeometryType::eHEIGHTFIELD: put(geometry); break; + case PxGeometryType::eGEOMETRY_COUNT: + case PxGeometryType::eINVALID: break; + } + } + + PX_FORCE_INLINE PxGeometryHolder() {} + PX_FORCE_INLINE PxGeometryHolder(const PxGeometry& geometry){ storeAny(geometry); } + + private: + template void put(const PxGeometry& geometry) + { + static_cast(any()) = static_cast(geometry); + } + + template T& get() + { + PX_ASSERT(getType() == type); + return static_cast(any()); + } + + template T& get() const + { + PX_ASSERT(getType() == type); + return static_cast(any()); + } + + union { + PxU8 geometry[sizeof(PxGeometry)]; + PxU8 box[sizeof(PxBoxGeometry)]; + PxU8 sphere[sizeof(PxSphereGeometry)]; + PxU8 capsule[sizeof(PxCapsuleGeometry)]; + PxU8 plane[sizeof(PxPlaneGeometry)]; + PxU8 convex[sizeof(PxConvexMeshGeometry)]; + PxU8 mesh[sizeof(PxTriangleMeshGeometry)]; + PxU8 heightfield[sizeof(PxHeightFieldGeometry)]; + } bytes; +} +PX_ALIGN_SUFFIX(4); + + + + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/geometry/PxGeometryQuery.h b/sources/PhysX/PhysX/include/geometry/PxGeometryQuery.h new file mode 100644 index 00000000..a4cab1a7 --- /dev/null +++ b/sources/PhysX/PhysX/include/geometry/PxGeometryQuery.h @@ -0,0 +1,225 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_GEOMUTILS_PX_GEOMETRY_QUERY +#define PX_PHYSICS_GEOMUTILS_PX_GEOMETRY_QUERY + +/** +\brief Maximum sweep distance for scene sweeps. The distance parameter for sweep functions will be clamped to this value. +The reason for this is GJK support cannot be evaluated near infinity. A viable alternative can be a sweep followed by an infinite raycast. + +@see PxScene +*/ +#define PX_MAX_SWEEP_DISTANCE 1e8f + +/** \addtogroup geomutils + @{ +*/ + +#include "common/PxPhysXCommonConfig.h" +#include "PxQueryReport.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxGeometry; +struct PxSweepHit; +struct PxRaycastHit; + +class PxTriangle; + +/** +\brief Collection of geometry object queries (sweeps, raycasts, overlaps, ...). +*/ +class PxGeometryQuery +{ +public: + + /** + \brief Sweep a specified geometry object in space and test for collision with a given object. + + The following combinations are supported. + + \li PxSphereGeometry vs. {PxSphereGeometry, PxPlaneGeometry, PxCapsuleGeometry, PxBoxGeometry, PxConvexMeshGeometry, PxTriangleMeshGeometry, PxHeightFieldGeometry} + \li PxCapsuleGeometry vs. {PxSphereGeometry, PxPlaneGeometry, PxCapsuleGeometry, PxBoxGeometry, PxConvexMeshGeometry, PxTriangleMeshGeometry, PxHeightFieldGeometry} + \li PxBoxGeometry vs. {PxSphereGeometry, PxPlaneGeometry, PxCapsuleGeometry, PxBoxGeometry, PxConvexMeshGeometry, PxTriangleMeshGeometry, PxHeightFieldGeometry} + \li PxConvexMeshGeometry vs. {PxSphereGeometry, PxPlaneGeometry, PxCapsuleGeometry, PxBoxGeometry, PxConvexMeshGeometry, PxTriangleMeshGeometry, PxHeightFieldGeometry} + + \param[in] unitDir Normalized direction along which object geom0 should be swept + \param[in] maxDist Maximum sweep distance, has to be in the [0, inf) range + \param[in] geom0 The geometry object to sweep. Supported geometries are #PxSphereGeometry, #PxCapsuleGeometry, #PxBoxGeometry and #PxConvexMeshGeometry + \param[in] pose0 Pose of the geometry object to sweep + \param[in] geom1 The geometry object to test the sweep against + \param[in] pose1 Pose of the geometry object to sweep against + \param[out] sweepHit The sweep hit information. Only valid if this method returns true. + \param[in] hitFlags Specify which properties per hit should be computed and written to result hit array. Combination of #PxHitFlag flags + \param[in] inflation Surface of the swept shape is additively extruded in the normal direction, rounding corners and edges. + + \return True if the swept geometry object geom0 hits the object geom1 + + @see PxSweepHit PxGeometry PxTransform + */ + PX_PHYSX_COMMON_API static bool sweep(const PxVec3& unitDir, + const PxReal maxDist, + const PxGeometry& geom0, + const PxTransform& pose0, + const PxGeometry& geom1, + const PxTransform& pose1, + PxSweepHit& sweepHit, + PxHitFlags hitFlags = PxHitFlag::eDEFAULT, + const PxReal inflation = 0.f); + + + /** + \brief Overlap test for two geometry objects. + + All combinations are supported except: + \li PxPlaneGeometry vs. {PxPlaneGeometry, PxTriangleMeshGeometry, PxHeightFieldGeometry} + \li PxTriangleMeshGeometry vs. {PxTriangleMeshGeometry, PxHeightFieldGeometry} + \li PxHeightFieldGeometry vs. {PxHeightFieldGeometry} + + \param[in] geom0 The first geometry object + \param[in] pose0 Pose of the first geometry object + \param[in] geom1 The second geometry object + \param[in] pose1 Pose of the second geometry object + \return True if the two geometry objects overlap + + @see PxGeometry PxTransform + */ + PX_PHYSX_COMMON_API static bool overlap(const PxGeometry& geom0, const PxTransform& pose0, + const PxGeometry& geom1, const PxTransform& pose1); + + + /** + \brief Raycast test against a geometry object. + + \param[in] origin The origin of the ray to test the geometry object against + \param[in] unitDir Normalized direction of the ray to test the geometry object against + \param[in] geom The geometry object to test the ray against + \param[in] pose Pose of the geometry object + \param[in] maxDist Maximum ray length, has to be in the [0, inf) range + \param[in] hitFlags Specification of the kind of information to retrieve on hit. Combination of #PxHitFlag flags + \param[in] maxHits max number of returned hits = size of 'rayHits' buffer + \param[out] rayHits Raycast hits information + \return Number of hits between the ray and the geometry object + + @see PxRaycastHit PxGeometry PxTransform + */ + PX_PHYSX_COMMON_API static PxU32 raycast(const PxVec3& origin, + const PxVec3& unitDir, + const PxGeometry& geom, + const PxTransform& pose, + PxReal maxDist, + PxHitFlags hitFlags, + PxU32 maxHits, + PxRaycastHit* PX_RESTRICT rayHits); + + /** + \brief Compute minimum translational distance (MTD) between two geometry objects. + + All combinations of geom objects are supported except: + - plane/plane + - plane/mesh + - plane/heightfield + - mesh/mesh + - mesh/heightfield + - heightfield/heightfield + + The function returns a unit vector ('direction') and a penetration depth ('depth'). + + The depenetration vector D = direction * depth should be applied to the first object, to + get out of the second object. + + Returned depth should always be positive or null. + + If objects do not overlap, the function can not compute the MTD and returns false. + + \param[out] direction Computed MTD unit direction + \param[out] depth Penetration depth. Always positive or null. + \param[in] geom0 The first geometry object + \param[in] pose0 Pose of the first geometry object + \param[in] geom1 The second geometry object + \param[in] pose1 Pose of the second geometry object + \return True if the MTD has successfully been computed, i.e. if objects do overlap. + + @see PxGeometry PxTransform + */ + PX_PHYSX_COMMON_API static bool computePenetration(PxVec3& direction, PxF32& depth, + const PxGeometry& geom0, const PxTransform& pose0, + const PxGeometry& geom1, const PxTransform& pose1); + + /** + \brief Computes distance between a point and a geometry object. + + Currently supported geometry objects: box, sphere, capsule, convex. + + \param[in] point The point P + \param[in] geom The geometry object + \param[in] pose Pose of the geometry object + \param[out] closestPoint Optionally returned closest point to P on the geom object. Only valid when returned distance is strictly positive. + \return Square distance between the point and the geom object, or 0.0 if the point is inside the object, or -1.0 if the geometry type is not supported. + + @see PxGeometry PxTransform + */ + PX_PHYSX_COMMON_API static PxReal pointDistance(const PxVec3& point, const PxGeometry& geom, const PxTransform& pose, PxVec3* closestPoint=NULL); + + + /** + \brief get the bounds for a geometry object + + \param[in] geom The geometry object + \param[in] pose Pose of the geometry object + \param[in] inflation Scale factor for computed world bounds. Box extents are multiplied by this value. + \return The bounds of the object + + @see PxGeometry PxTransform + */ + PX_PHYSX_COMMON_API static PxBounds3 getWorldBounds(const PxGeometry& geom, const PxTransform& pose, float inflation=1.01f); + + /** + \brief Checks if provided geometry is valid. + + \param[in] geom The geometry object. + \return True if geometry is valid. + + @see PxGeometry PxSphereGeometry, PxCapsuleGeometry, PxBoxGeometry, PxConvexGeometry + */ + PX_PHYSX_COMMON_API static bool isValid(const PxGeometry& geom); +}; + + +#if !PX_DOXYGEN +} +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/geometry/PxHeightField.h b/sources/PhysX/PhysX/include/geometry/PxHeightField.h new file mode 100644 index 00000000..34665956 --- /dev/null +++ b/sources/PhysX/PhysX/include/geometry/PxHeightField.h @@ -0,0 +1,262 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_GEOMUTILS_NX_HEIGHTFIELD +#define PX_PHYSICS_GEOMUTILS_NX_HEIGHTFIELD +/** \addtogroup geomutils + @{ +*/ + +#include "geometry/PxHeightFieldFlag.h" +#include "geometry/PxHeightFieldSample.h" +#include "common/PxBase.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxHeightFieldDesc; + +/** +\brief A height field class. + +Height fields work in a similar way as triangle meshes specified to act as +height fields, with some important differences: + +Triangle meshes can be made of nonuniform geometry, while height fields are +regular, rectangular grids. This means that with PxHeightField, you sacrifice +flexibility in return for improved performance and decreased memory consumption. + +In local space rows extend in X direction, columns in Z direction and height in Y direction. + +Like Convexes and TriangleMeshes, HeightFields are referenced by shape instances +(see #PxHeightFieldGeometry, #PxShape). + +To avoid duplicating data when you have several instances of a particular +height field differently, you do not use this class to represent a +height field object directly. Instead, you create an instance of this height field +via the PxHeightFieldGeometry and PxShape classes. + +

Creation

+ +To create an instance of this class call PxPhysics::createHeightField() or +PxCooking::createHeightField(const PxHeightFieldDesc&, PxPhysicsInsertionCallback&). +To delete it call release(). This is only possible +once you have released all of its PxHeightFiedShape instances. + +

Visualizations:

+\li #PxVisualizationParameter::eCOLLISION_AABBS +\li #PxVisualizationParameter::eCOLLISION_SHAPES +\li #PxVisualizationParameter::eCOLLISION_AXES +\li #PxVisualizationParameter::eCOLLISION_FNORMALS +\li #PxVisualizationParameter::eCOLLISION_EDGES + +@see PxHeightFieldDesc PxHeightFieldGeometry PxShape PxPhysics.createHeightField() PxCooking.createHeightField() +*/ + +class PxHeightField : public PxBase +{ + public: + /** + \brief Decrements the reference count of a height field and releases it if the new reference count is zero. + + @see PxPhysics.createHeightField() PxHeightFieldDesc PxHeightFieldGeometry PxShape + */ + PX_PHYSX_COMMON_API virtual void release() = 0; + + /** + \brief Writes out the sample data array. + + The user provides destBufferSize bytes storage at destBuffer. + The data is formatted and arranged as PxHeightFieldDesc.samples. + + \param[out] destBuffer The destination buffer for the sample data. + \param[in] destBufferSize The size of the destination buffer. + \return The number of bytes written. + + @see PxHeightFieldDesc.samples + */ + PX_PHYSX_COMMON_API virtual PxU32 saveCells(void* destBuffer, PxU32 destBufferSize) const = 0; + + /** + \brief Replaces a rectangular subfield in the sample data array. + + The user provides the description of a rectangular subfield in subfieldDesc. + The data is formatted and arranged as PxHeightFieldDesc.samples. + + \param[in] startCol First cell in the destination heightfield to be modified. Can be negative. + \param[in] startRow First row in the destination heightfield to be modified. Can be negative. + \param[in] subfieldDesc Description of the source subfield to read the samples from. + \param[in] shrinkBounds If left as false, the bounds will never shrink but only grow. If set to true the bounds will be recomputed from all HF samples at O(nbColums*nbRows) perf cost. + \return True on success, false on failure. Failure can occur due to format mismatch. + + \note Modified samples are constrained to the same height quantization range as the original heightfield. + Source samples that are out of range of target heightfield will be clipped with no error. + PhysX does not keep a mapping from the heightfield to heightfield shapes that reference it. + Call PxShape::setGeometry on each shape which references the height field, to ensure that internal data structures are updated to reflect the new geometry. + Please note that PxShape::setGeometry does not guarantee correct/continuous behavior when objects are resting on top of old or new geometry. + + @see PxHeightFieldDesc.samples PxShape.setGeometry + */ + PX_PHYSX_COMMON_API virtual bool modifySamples(PxI32 startCol, PxI32 startRow, const PxHeightFieldDesc& subfieldDesc, bool shrinkBounds = false) = 0; + + /** + \brief Retrieves the number of sample rows in the samples array. + + \return The number of sample rows in the samples array. + + @see PxHeightFieldDesc.nbRows + */ + PX_PHYSX_COMMON_API virtual PxU32 getNbRows() const = 0; + + /** + \brief Retrieves the number of sample columns in the samples array. + + \return The number of sample columns in the samples array. + + @see PxHeightFieldDesc.nbColumns + */ + PX_PHYSX_COMMON_API virtual PxU32 getNbColumns() const = 0; + + /** + \brief Retrieves the format of the sample data. + + \return The format of the sample data. + + @see PxHeightFieldDesc.format PxHeightFieldFormat + */ + PX_PHYSX_COMMON_API virtual PxHeightFieldFormat::Enum getFormat() const = 0; + + /** + \brief Retrieves the offset in bytes between consecutive samples in the array. + + \return The offset in bytes between consecutive samples in the array. + + @see PxHeightFieldDesc.sampleStride + */ + PX_PHYSX_COMMON_API virtual PxU32 getSampleStride() const = 0; + + /** + \brief Retrieves the convex edge threshold. + + \return The convex edge threshold. + + @see PxHeightFieldDesc.convexEdgeThreshold + */ + PX_PHYSX_COMMON_API virtual PxReal getConvexEdgeThreshold() const = 0; + + /** + \brief Retrieves the flags bits, combined from values of the enum ::PxHeightFieldFlag. + + \return The flags bits, combined from values of the enum ::PxHeightFieldFlag. + + @see PxHeightFieldDesc.flags PxHeightFieldFlag + */ + PX_PHYSX_COMMON_API virtual PxHeightFieldFlags getFlags() const = 0; + + /** + \brief Retrieves the height at the given coordinates in grid space. + + \return The height at the given coordinates or 0 if the coordinates are out of range. + */ + PX_PHYSX_COMMON_API virtual PxReal getHeight(PxReal x, PxReal z) const = 0; + + /** + \brief Returns the reference count for shared heightfields. + + At creation, the reference count of the heightfield is 1. Every shape referencing this heightfield increments the + count by 1. When the reference count reaches 0, and only then, the heightfield gets destroyed automatically. + + \return the current reference count. + */ + PX_PHYSX_COMMON_API virtual PxU32 getReferenceCount() const = 0; + + /** + \brief Acquires a counted reference to a heightfield. + + This method increases the reference count of the heightfield by 1. Decrement the reference count by calling release() + */ + PX_PHYSX_COMMON_API virtual void acquireReference() = 0; + + /** + \brief Returns material table index of given triangle + + \note This function takes a post cooking triangle index. + + \param[in] triangleIndex (internal) index of desired triangle + \return Material table index, or 0xffff if no per-triangle materials are used + */ + PX_PHYSX_COMMON_API virtual PxMaterialTableIndex getTriangleMaterialIndex(PxTriangleID triangleIndex) const = 0; + + /** + \brief Returns a triangle face normal for a given triangle index + + \note This function takes a post cooking triangle index. + + \param[in] triangleIndex (internal) index of desired triangle + \return Triangle normal for a given triangle index + */ + PX_PHYSX_COMMON_API virtual PxVec3 getTriangleNormal(PxTriangleID triangleIndex) const = 0; + + /** + \brief Returns heightfield sample of given row and column + + \param[in] row Given heightfield row + \param[in] column Given heightfield column + \return Heightfield sample + */ + PX_PHYSX_COMMON_API virtual const PxHeightFieldSample& getSample(PxU32 row, PxU32 column) const = 0; + + /** + \brief Returns the number of times the heightfield data has been modified + + This method returns the number of times modifySamples has been called on this heightfield, so that code that has + retained state that depends on the heightfield can efficiently determine whether it has been modified. + + \return the number of times the heightfield sample data has been modified. + */ + PX_PHYSX_COMMON_API virtual PxU32 getTimestamp() const = 0; + + PX_PHYSX_COMMON_API virtual const char* getConcreteTypeName() const { return "PxHeightField"; } + +protected: + PX_INLINE PxHeightField(PxType concreteType, PxBaseFlags baseFlags) : PxBase(concreteType, baseFlags) {} + PX_INLINE PxHeightField(PxBaseFlags baseFlags) : PxBase(baseFlags) {} + PX_PHYSX_COMMON_API virtual ~PxHeightField() {} + PX_PHYSX_COMMON_API virtual bool isKindOf(const char* name) const { return !::strcmp("PxHeightField", name) || PxBase::isKindOf(name); } +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/geometry/PxHeightFieldDesc.h b/sources/PhysX/PhysX/include/geometry/PxHeightFieldDesc.h new file mode 100644 index 00000000..669e9155 --- /dev/null +++ b/sources/PhysX/PhysX/include/geometry/PxHeightFieldDesc.h @@ -0,0 +1,187 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_COLLISION_NXHEIGHTFIELDDESC +#define PX_COLLISION_NXHEIGHTFIELDDESC +/** \addtogroup geomutils +@{ +*/ + +#include "common/PxPhysXCommonConfig.h" +#include "geometry/PxHeightFieldFlag.h" +#include "common/PxCoreUtilityTypes.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief Descriptor class for #PxHeightField. + +\note The heightfield data is *copied* when a PxHeightField object is created from this descriptor. After the call the +user may discard the height data. + +@see PxHeightField PxHeightFieldGeometry PxShape PxPhysics.createHeightField() PxCooking.createHeightField() +*/ +class PxHeightFieldDesc +{ +public: + + /** + \brief Number of sample rows in the height field samples array. + + \note Local space X-axis corresponds to rows. + + Range: >1
+ Default: 0 + */ + PxU32 nbRows; + + /** + \brief Number of sample columns in the height field samples array. + + \note Local space Z-axis corresponds to columns. + + Range: >1
+ Default: 0 + */ + PxU32 nbColumns; + + /** + \brief Format of the sample data. + + Currently the only supported format is PxHeightFieldFormat::eS16_TM: + + Default: PxHeightFieldFormat::eS16_TM + + @see PxHeightFormat PxHeightFieldDesc.samples + */ + PxHeightFieldFormat::Enum format; + + /** + \brief The samples array. + + It is copied to the SDK's storage at creation time. + + There are nbRows * nbColumn samples in the array, + which define nbRows * nbColumn vertices and cells, + of which (nbRows - 1) * (nbColumns - 1) cells are actually used. + + The array index of sample(row, column) = row * nbColumns + column. + The byte offset of sample(row, column) = sampleStride * (row * nbColumns + column). + The sample data follows at the offset and spans the number of bytes defined by the format. + Then there are zero or more unused bytes depending on sampleStride before the next sample. + + Default: NULL + + @see PxHeightFormat + */ + PxStridedData samples; + + /** + This threshold is used by the collision detection to determine if a height field edge is convex + and can generate contact points. + Usually the convexity of an edge is determined from the angle (or cosine of the angle) between + the normals of the faces sharing that edge. + The height field allows a more efficient approach by comparing height values of neighboring vertices. + This parameter offsets the comparison. Smaller changes than 0.5 will not alter the set of convex edges. + The rule of thumb is that larger values will result in fewer edge contacts. + + This parameter is ignored in contact generation with sphere and capsule primitives. + + Range: [0, PX_MAX_F32)
+ Default: 0 + */ + PxReal convexEdgeThreshold; + + /** + \brief Flags bits, combined from values of the enum ::PxHeightFieldFlag. + + Default: 0 + + @see PxHeightFieldFlag PxHeightFieldFlags + */ + PxHeightFieldFlags flags; + + /** + \brief Constructor sets to default. + */ + PX_INLINE PxHeightFieldDesc(); + + /** + \brief (re)sets the structure to the default. + */ + PX_INLINE void setToDefault(); + + /** + \brief Returns true if the descriptor is valid. + \return True if the current settings are valid. + */ + PX_INLINE bool isValid() const; +}; + +PX_INLINE PxHeightFieldDesc::PxHeightFieldDesc() //constructor sets to default +{ + nbColumns = 0; + nbRows = 0; + format = PxHeightFieldFormat::eS16_TM; + convexEdgeThreshold = 0.0f; + flags = PxHeightFieldFlags(); +} + +PX_INLINE void PxHeightFieldDesc::setToDefault() +{ + *this = PxHeightFieldDesc(); +} + +PX_INLINE bool PxHeightFieldDesc::isValid() const +{ + if (nbColumns < 2) + return false; + if (nbRows < 2) + return false; + if(format != PxHeightFieldFormat::eS16_TM) + return false; + if (samples.stride < 4) + return false; + if (convexEdgeThreshold < 0) + return false; + if ((flags & PxHeightFieldFlag::eNO_BOUNDARY_EDGES) != flags) + return false; + return true; +} + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/geometry/PxHeightFieldFlag.h b/sources/PhysX/PhysX/include/geometry/PxHeightFieldFlag.h new file mode 100644 index 00000000..85b27a33 --- /dev/null +++ b/sources/PhysX/PhysX/include/geometry/PxHeightFieldFlag.h @@ -0,0 +1,162 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_COLLISION_NXHEIGHTFIELDFLAG +#define PX_COLLISION_NXHEIGHTFIELDFLAG +/** \addtogroup geomutils +@{ +*/ + +#include "foundation/PxFlags.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief Describes the format of height field samples. +@see PxHeightFieldDesc.format PxHeightFieldDesc.samples +*/ +struct PxHeightFieldFormat +{ + enum Enum + { + /** + \brief Height field height data is 16 bit signed integers, followed by triangle materials. + + Each sample is 32 bits wide arranged as follows: + + \image html heightFieldFormat_S16_TM.png + + 1) First there is a 16 bit height value. + 2) Next, two one byte material indices, with the high bit of each byte reserved for special use. + (so the material index is only 7 bits). + The high bit of material0 is the tess-flag. + The high bit of material1 is reserved for future use. + + There are zero or more unused bytes before the next sample depending on PxHeightFieldDesc.sampleStride, + where the application may eventually keep its own data. + + This is the only format supported at the moment. + + @see PxHeightFieldDesc.format PxHeightFieldDesc.samples + */ + eS16_TM = (1 << 0) + }; +}; + +/** +\brief Determines the tessellation of height field cells. +@see PxHeightFieldDesc.format PxHeightFieldDesc.samples +*/ +struct PxHeightFieldTessFlag +{ + enum Enum + { + /** + \brief This flag determines which way each quad cell is subdivided. + + The flag lowered indicates subdivision like this: (the 0th vertex is referenced by only one triangle) + + \image html heightfieldTriMat2.PNG + +
+		+--+--+--+---> column
+		| /| /| /|
+		|/ |/ |/ |
+		+--+--+--+
+		| /| /| /|
+		|/ |/ |/ |
+		+--+--+--+
+		|
+		|
+		V row
+		
+ + The flag raised indicates subdivision like this: (the 0th vertex is shared by two triangles) + + \image html heightfieldTriMat1.PNG + +
+		+--+--+--+---> column
+		|\ |\ |\ |
+		| \| \| \|
+		+--+--+--+
+		|\ |\ |\ |
+		| \| \| \|
+		+--+--+--+
+		|
+		|
+		V row
+		
+ + @see PxHeightFieldDesc.format PxHeightFieldDesc.samples + */ + e0TH_VERTEX_SHARED = (1 << 0) + }; +}; + + +/** +\brief Enum with flag values to be used in PxHeightFieldDesc.flags. +*/ +struct PxHeightFieldFlag +{ + enum Enum + { + /** + \brief Disable collisions with height field with boundary edges. + + Raise this flag if several terrain patches are going to be placed adjacent to each other, + to avoid a bump when sliding across. + + This flag is ignored in contact generation with sphere and capsule shapes. + + @see PxHeightFieldDesc.flags + */ + eNO_BOUNDARY_EDGES = (1 << 0) + }; +}; + +/** +\brief collection of set bits defined in PxHeightFieldFlag. + +@see PxHeightFieldFlag +*/ +typedef PxFlags PxHeightFieldFlags; +PX_FLAGS_OPERATORS(PxHeightFieldFlag::Enum,PxU16) + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/geometry/PxHeightFieldGeometry.h b/sources/PhysX/PhysX/include/geometry/PxHeightFieldGeometry.h new file mode 100644 index 00000000..d32c1b89 --- /dev/null +++ b/sources/PhysX/PhysX/include/geometry/PxHeightFieldGeometry.h @@ -0,0 +1,143 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX_HEIGHTFIELD_GEOMETRY +#define PX_PHYSICS_NX_HEIGHTFIELD_GEOMETRY +/** \addtogroup geomutils +@{ +*/ +#include "geometry/PxTriangleMeshGeometry.h" +#include "common/PxCoreUtilityTypes.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +#define PX_MIN_HEIGHTFIELD_XZ_SCALE 1e-8f +#define PX_MIN_HEIGHTFIELD_Y_SCALE (0.0001f / PxReal(0xFFFF)) + +class PxHeightField; + +/** +\brief Height field geometry class. + +This class allows to create a scaled height field geometry instance. + +There is a minimum allowed value for Y and XZ scaling - PX_MIN_HEIGHTFIELD_XZ_SCALE, heightfield creation will fail if XZ value is below this value. +*/ +class PxHeightFieldGeometry : public PxGeometry +{ +public: + PX_INLINE PxHeightFieldGeometry() : + PxGeometry (PxGeometryType::eHEIGHTFIELD), + heightField (NULL), + heightScale (1.0f), + rowScale (1.0f), + columnScale (1.0f), + heightFieldFlags(0) + {} + + PX_INLINE PxHeightFieldGeometry(PxHeightField* hf, + PxMeshGeometryFlags flags, + PxReal heightScale_, + PxReal rowScale_, + PxReal columnScale_) : + PxGeometry (PxGeometryType::eHEIGHTFIELD), + heightField (hf) , + heightScale (heightScale_), + rowScale (rowScale_), + columnScale (columnScale_), + heightFieldFlags (flags) + { + } + + /** + \brief Returns true if the geometry is valid. + + \return True if the current settings are valid + + \note A valid height field has a positive scale value in each direction (heightScale > 0, rowScale > 0, columnScale > 0). + It is illegal to call PxRigidActor::createShape and PxPhysics::createShape with a height field that has zero extents in any direction. + + @see PxRigidActor::createShape, PxPhysics::createShape + */ + PX_INLINE bool isValid() const; + +public: + /** + \brief The height field data. + */ + PxHeightField* heightField; + + /** + \brief The scaling factor for the height field in vertical direction (y direction in local space). + */ + PxReal heightScale; + + /** + \brief The scaling factor for the height field in the row direction (x direction in local space). + */ + PxReal rowScale; + + /** + \brief The scaling factor for the height field in the column direction (z direction in local space). + */ + PxReal columnScale; + + /** + \brief Flags to specify some collision properties for the height field. + */ + PxMeshGeometryFlags heightFieldFlags; + + PxPadding<3> paddingFromFlags; //!< padding for mesh flags. +}; + + +PX_INLINE bool PxHeightFieldGeometry::isValid() const +{ + if (mType != PxGeometryType::eHEIGHTFIELD) + return false; + if (!PxIsFinite(heightScale) || !PxIsFinite(rowScale) || !PxIsFinite(columnScale)) + return false; + if (rowScale < PX_MIN_HEIGHTFIELD_XZ_SCALE || columnScale < PX_MIN_HEIGHTFIELD_XZ_SCALE || heightScale < PX_MIN_HEIGHTFIELD_Y_SCALE) + return false; + if (!heightField) + return false; + + return true; +} + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/geometry/PxHeightFieldSample.h b/sources/PhysX/PhysX/include/geometry/PxHeightFieldSample.h new file mode 100644 index 00000000..a0489974 --- /dev/null +++ b/sources/PhysX/PhysX/include/geometry/PxHeightFieldSample.h @@ -0,0 +1,124 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NXHEIGHTFIELDSAMPLE +#define PX_PHYSICS_NXHEIGHTFIELDSAMPLE +/** \addtogroup geomutils +@{ */ + +#include "common/PxPhysXCommonConfig.h" +#include "foundation/PxBitAndData.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief Special material index values for height field samples. + +@see PxHeightFieldSample.materialIndex0 PxHeightFieldSample.materialIndex1 +*/ +struct PxHeightFieldMaterial +{ + enum Enum + { + eHOLE = 127 //!< A material indicating that the triangle should be treated as a hole in the mesh. + }; +}; + +/** +\brief Heightfield sample format. + +This format corresponds to the #PxHeightFieldFormat member PxHeightFieldFormat::eS16_TM. + +An array of heightfield samples are used when creating a PxHeightField to specify +the elevation of the heightfield points. In addition the material and tessellation of the adjacent +triangles are specified. + +@see PxHeightField PxHeightFieldDesc PxHeightFieldDesc.samples +*/ +struct PxHeightFieldSample +{ +//= ATTENTION! ===================================================================================== +// Changing the data layout of this class breaks the binary serialization format. See comments for +// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData +// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION +// accordingly. +//================================================================================================== + + /** + \brief The height of the heightfield sample + + This value is scaled by PxHeightFieldGeometry::heightScale. + + @see PxHeightFieldGeometry + */ + PxI16 height; + + /** + \brief The triangle material index of the quad's lower triangle + tesselation flag + + An index pointing into the material table of the shape which instantiates the heightfield. + This index determines the material of the lower of the quad's two triangles (i.e. the quad whose + upper-left corner is this sample, see the Guide for illustrations). + + Special values of the 7 data bits are defined by PxHeightFieldMaterial + + The tesselation flag specifies which way the quad is split whose upper left corner is this sample. + If the flag is set, the diagonal of the quad will run from this sample to the opposite vertex; if not, + it will run between the other two vertices (see the Guide for illustrations). + + @see PxHeightFieldGeometry materialIndex1 PxShape.setmaterials() PxShape.getMaterials() + */ + PxBitAndByte materialIndex0; + + PX_CUDA_CALLABLE PX_FORCE_INLINE PxU8 tessFlag() const { return PxU8(materialIndex0.isBitSet() ? 1 : 0); } // PT: explicit conversion to make sure we don't break the code + PX_CUDA_CALLABLE PX_FORCE_INLINE void setTessFlag() { materialIndex0.setBit(); } + PX_CUDA_CALLABLE PX_FORCE_INLINE void clearTessFlag() { materialIndex0.clearBit(); } + + /** + \brief The triangle material index of the quad's upper triangle + reserved flag + + An index pointing into the material table of the shape which instantiates the heightfield. + This index determines the material of the upper of the quad's two triangles (i.e. the quad whose + upper-left corner is this sample, see the Guide for illustrations). + + @see PxHeightFieldGeometry materialIndex0 PxShape.setmaterials() PxShape.getMaterials() + */ + PxBitAndByte materialIndex1; +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/geometry/PxMeshQuery.h b/sources/PhysX/PhysX/include/geometry/PxMeshQuery.h new file mode 100644 index 00000000..7a9cfb6f --- /dev/null +++ b/sources/PhysX/PhysX/include/geometry/PxMeshQuery.h @@ -0,0 +1,201 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_GEOMUTILS_PX_MESH_QUERY +#define PX_PHYSICS_GEOMUTILS_PX_MESH_QUERY + +/** \addtogroup geomutils + @{ +*/ + +#include "common/PxPhysXCommonConfig.h" +#include "PxQueryReport.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxGeometry; +class PxConvexMeshGeometry; +class PxTriangleMeshGeometry; +class PxHeightFieldGeometry; + +class PxTriangle; + +class PxMeshQuery +{ +public: + + /** + \brief Retrieves triangle data from a triangle ID. + + This function can be used together with #findOverlapTriangleMesh() to retrieve triangle properties. + + \param[in] triGeom Geometry of the triangle mesh to extract the triangle from. + \param[in] transform Transform for the triangle mesh + \param[in] triangleIndex The index of the triangle to retrieve. + \param[out] triangle Triangle points in world space. + \param[out] vertexIndices Returned vertex indices for given triangle + \param[out] adjacencyIndices Returned 3 triangle adjacency internal face indices (0xFFFFFFFF if no adjacency). The mesh must be cooked with cooking param buildTriangleAdjacencies enabled. + + \note This function will flip the triangle normal whenever triGeom.scale.hasNegativeDeterminant() is true. + + @see PxTriangle PxTriangleFlags PxTriangleID findOverlapTriangleMesh() + */ + PX_PHYSX_COMMON_API static void getTriangle(const PxTriangleMeshGeometry& triGeom, const PxTransform& transform, PxTriangleID triangleIndex, PxTriangle& triangle, PxU32* vertexIndices=NULL, PxU32* adjacencyIndices=NULL); + + + /** + \brief Retrieves triangle data from a triangle ID. + + This function can be used together with #findOverlapHeightField() to retrieve triangle properties. + + \param[in] hfGeom Geometry of the height field to extract the triangle from. + \param[in] transform Transform for the height field. + \param[in] triangleIndex The index of the triangle to retrieve. + \param[out] triangle Triangle points in world space. + \param[out] vertexIndices Returned vertex indices for given triangle + \param[out] adjacencyIndices Returned 3 triangle adjacency triangle indices (0xFFFFFFFF if no adjacency). + + \note This function will flip the triangle normal whenever triGeom.scale.hasNegativeDeterminant() is true. + \note TriangleIndex is an index used in internal format, which does have an index out of the bounds in last row. + To traverse all tri indices in the HF, the following code can be applied: + for (PxU32 row = 0; row < (nbRows - 1); row++) + { + for (PxU32 col = 0; col < (nbCols - 1); col++) + { + for (PxU32 k = 0; k < 2; k++) + { + const PxU32 triIndex = 2 * (row*nbCols + col) + k; + .... + } + } + } + @see PxTriangle PxTriangleFlags PxTriangleID findOverlapHeightField() + */ + PX_PHYSX_COMMON_API static void getTriangle(const PxHeightFieldGeometry& hfGeom, const PxTransform& transform, PxTriangleID triangleIndex, PxTriangle& triangle, PxU32* vertexIndices=NULL, PxU32* adjacencyIndices=NULL); + + + /** + \brief Find the mesh triangles which touch the specified geometry object. + + Returned triangle indices can be used with #getTriangle() to retrieve the triangle properties. + + \param[in] geom The geometry object to test for mesh triangle overlaps. Supported geometries are #PxSphereGeometry, #PxCapsuleGeometry and #PxBoxGeometry + \param[in] geomPose Pose of the geometry object + \param[in] meshGeom The triangle mesh geometry to check overlap against + \param[in] meshPose Pose of the triangle mesh + \param[out] results Indices of overlapping triangles + \param[in] maxResults Size of 'results' buffer + \param[in] startIndex Index of first result to be retrieved. Previous indices are skipped. + \param[out] overflow True if a buffer overflow occurred + \return Number of overlaps found, i.e. number of elements written to the results buffer + + @see PxTriangleMeshGeometry getTriangle() + */ + PX_PHYSX_COMMON_API static PxU32 findOverlapTriangleMesh( const PxGeometry& geom, const PxTransform& geomPose, + const PxTriangleMeshGeometry& meshGeom, const PxTransform& meshPose, + PxU32* results, PxU32 maxResults, PxU32 startIndex, bool& overflow); + + /** + \brief Find the height field triangles which touch the specified geometry object. + + Returned triangle indices can be used with #getTriangle() to retrieve the triangle properties. + + \param[in] geom The geometry object to test for height field overlaps. Supported geometries are #PxSphereGeometry, #PxCapsuleGeometry and #PxBoxGeometry. The sphere and capsule queries are currently conservative estimates. + \param[in] geomPose Pose of the geometry object + \param[in] hfGeom The height field geometry to check overlap against + \param[in] hfPose Pose of the height field + \param[out] results Indices of overlapping triangles + \param[in] maxResults Size of 'results' buffer + \param[in] startIndex Index of first result to be retrieved. Previous indices are skipped. + \param[out] overflow True if a buffer overflow occurred + \return Number of overlaps found, i.e. number of elements written to the results buffer + + @see PxHeightFieldGeometry getTriangle() + */ + PX_PHYSX_COMMON_API static PxU32 findOverlapHeightField(const PxGeometry& geom, const PxTransform& geomPose, + const PxHeightFieldGeometry& hfGeom, const PxTransform& hfPose, + PxU32* results, PxU32 maxResults, PxU32 startIndex, bool& overflow); + + + /** + \brief Sweep a specified geometry object in space and test for collision with a set of given triangles. + + This function simply sweeps input geometry against each input triangle, in the order they are given. + This is an O(N) operation with N = number of input triangles. It does not use any particular acceleration structure. + + \param[in] unitDir Normalized direction of the sweep. + \param[in] distance Sweep distance. Needs to be larger than 0. Clamped to PX_MAX_SWEEP_DISTANCE. + \param[in] geom The geometry object to sweep. Supported geometries are #PxSphereGeometry, #PxCapsuleGeometry and #PxBoxGeometry + \param[in] pose Pose of the geometry object to sweep. + \param[in] triangleCount Number of specified triangles + \param[in] triangles Array of triangles to sweep against + \param[out] sweepHit The sweep hit information. See the notes below for limitations about returned results. + \param[in] hitFlags Specification of the kind of information to retrieve on hit. Combination of #PxHitFlag flags. See the notes below for limitations about supported flags. + \param[in] cachedIndex Cached triangle index for subsequent calls. Cached triangle is tested first. Optional parameter. + \param[in] inflation This parameter creates a skin around the swept geometry which increases its extents for sweeping. The sweep will register a hit as soon as the skin touches a shape, and will return the corresponding distance and normal. + \param[in] doubleSided Counterpart of PxMeshGeometryFlag::eDOUBLE_SIDED for input triangles. + \return True if the swept geometry object hits the specified triangles + + \note Only the following geometry types are currently supported: PxSphereGeometry, PxCapsuleGeometry, PxBoxGeometry + \note If a shape from the scene is already overlapping with the query shape in its starting position, the hit is returned unless eASSUME_NO_INITIAL_OVERLAP was specified. + \note This function returns a single closest hit across all the input triangles. Multiple hits are not supported. + \note Supported hitFlags are PxHitFlag::eDEFAULT, PxHitFlag::eASSUME_NO_INITIAL_OVERLAP, PxHitFlag::ePRECISE_SWEEP, PxHitFlag::eMESH_BOTH_SIDES, PxHitFlag::eMESH_ANY. + \note ePOSITION is only defined when there is no initial overlap (sweepHit.hadInitialOverlap() == false) + \note The returned normal for initially overlapping sweeps is set to -unitDir. + \note Otherwise the returned normal is the front normal of the triangle even if PxHitFlag::eMESH_BOTH_SIDES is set. + \note The returned PxSweepHit::faceIndex parameter will hold the index of the hit triangle in input array, i.e. the range is [0; triangleCount). For initially overlapping sweeps, this is the index of overlapping triangle. + \note The returned PxSweepHit::actor and PxSweepHit::shape pointers are not filled. + \note The inflation parameter is not compatible with PxHitFlag::ePRECISE_SWEEP. + + @see PxTriangle PxSweepHit PxGeometry PxTransform + */ + PX_PHYSX_COMMON_API static bool sweep(const PxVec3& unitDir, + const PxReal distance, + const PxGeometry& geom, + const PxTransform& pose, + PxU32 triangleCount, + const PxTriangle* triangles, + PxSweepHit& sweepHit, + PxHitFlags hitFlags = PxHitFlag::eDEFAULT, + const PxU32* cachedIndex = NULL, + const PxReal inflation = 0.0f, + bool doubleSided = false); +}; + + +#if !PX_DOXYGEN +} +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/geometry/PxMeshScale.h b/sources/PhysX/PhysX/include/geometry/PxMeshScale.h new file mode 100644 index 00000000..02bf3659 --- /dev/null +++ b/sources/PhysX/PhysX/include/geometry/PxMeshScale.h @@ -0,0 +1,175 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX_MESHSCALE +#define PX_PHYSICS_NX_MESHSCALE +/** \addtogroup geomutils +@{ +*/ + +#include "common/PxPhysXCommonConfig.h" +#include "foundation/PxMat33.h" +#include "foundation/PxAssert.h" + +/** \brief Minimum allowed absolute magnitude for each of mesh scale's components (x,y,z). + \note Only positive scale values are allowed for convex meshes. */ +#define PX_MESH_SCALE_MIN 1e-6f + +/** \brief Maximum allowed absolute magnitude for each of mesh scale's components (x,y,z). + \note Only positive scale values are allowed for convex meshes. */ +#define PX_MESH_SCALE_MAX 1e6f + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief A class expressing a nonuniform scaling transformation. + +The scaling is along arbitrary axes that are specified by PxMeshScale::rotation. + +\note Negative scale values are supported for PxTriangleMeshGeometry + with absolute values for each component within [PX_MIN_ABS_MESH_SCALE, PX_MAX_ABS_MESH_SCALE] range. + Negative scale causes a reflection around the specified axis, in addition PhysX will flip the normals + for mesh triangles when scale.x*scale.y*scale.z < 0. +\note Only positive scale values are supported for PxConvexMeshGeometry + with values for each component within [PX_MIN_ABS_MESH_SCALE, PX_MAX_ABS_MESH_SCALE] range). + +@see PxConvexMeshGeometry PxTriangleMeshGeometry +*/ +class PxMeshScale +{ +//= ATTENTION! ===================================================================================== +// Changing the data layout of this class breaks the binary serialization format. See comments for +// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData +// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION +// accordingly. +//================================================================================================== +public: + /** + \brief Constructor initializes to identity scale. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxMeshScale(): scale(1.0f), rotation(PxIdentity) + { + } + + /** + \brief Constructor from scalar. + */ + explicit PX_CUDA_CALLABLE PX_FORCE_INLINE PxMeshScale(PxReal r): scale(r), rotation(PxIdentity) + { + } + + /** + \brief Constructor to initialize to arbitrary scale and identity scale rotation. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxMeshScale(const PxVec3& s) + { + scale = s; + rotation = PxQuat(PxIdentity); + } + + /** + \brief Constructor to initialize to arbitrary scaling. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxMeshScale(const PxVec3& s, const PxQuat& r) + { + PX_ASSERT(r.isUnit()); + scale = s; + rotation = r; + } + + + /** + \brief Returns true if the scaling is an identity transformation. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE bool isIdentity() const + { + return (scale.x == 1.0f && scale.y == 1.0f && scale.z == 1.0f); + } + + /** + \brief Returns the inverse of this scaling transformation. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxMeshScale getInverse() const + { + return PxMeshScale(PxVec3(1.0f/scale.x, 1.0f/scale.y, 1.0f/scale.z), rotation); + } + + /** + \brief Converts this transformation to a 3x3 matrix representation. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxMat33 toMat33() const + { + PxMat33 rot(rotation); + PxMat33 trans = rot.getTranspose(); + trans.column0 *= scale[0]; + trans.column1 *= scale[1]; + trans.column2 *= scale[2]; + return trans * rot; + } + + /** + \brief Returns true if combination of negative scale components will cause the triangle normal to flip. The SDK will flip the normals internally. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE bool hasNegativeDeterminant() const + { + return (scale.x * scale.y * scale.z < 0.0f); + } + + PxVec3 transform(const PxVec3& v) const + { + return rotation.rotateInv(scale.multiply(rotation.rotate(v))); + } + + bool isValidForTriangleMesh() const + { + PxVec3 absXYZ = scale.abs(); + return (absXYZ.maxElement() <= PX_MESH_SCALE_MAX) && (absXYZ.minElement() >= PX_MESH_SCALE_MIN); + } + + bool isValidForConvexMesh() const + { + return (scale.maxElement() <= PX_MESH_SCALE_MAX) && (scale.minElement() >= PX_MESH_SCALE_MIN); + } + + PxVec3 scale; //!< A nonuniform scaling + PxQuat rotation; //!< The orientation of the scaling axes + + +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/geometry/PxPlaneGeometry.h b/sources/PhysX/PhysX/include/geometry/PxPlaneGeometry.h new file mode 100644 index 00000000..cbc80e8d --- /dev/null +++ b/sources/PhysX/PhysX/include/geometry/PxPlaneGeometry.h @@ -0,0 +1,108 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX_PLANE_GEOMETRY +#define PX_PHYSICS_NX_PLANE_GEOMETRY +/** \addtogroup geomutils +@{ +*/ +#include "foundation/PxPlane.h" +#include "foundation/PxTransform.h" +#include "geometry/PxGeometry.h" +#include "foundation/PxFoundationConfig.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief Class describing a plane geometry. + +The plane geometry specifies the half-space volume x<=0. As with other geometry types, +when used in a PxShape the collision volume is obtained by transforming the halfspace +by the shape local pose and the actor global pose. + +To generate a PxPlane from a PxTransform, transform PxPlane(1,0,0,0). + +To generate a PxTransform from a PxPlane, use PxTransformFromPlaneEquation. + +@see PxShape.setGeometry() PxShape.getPlaneGeometry() PxTransformFromPlaneEquation +*/ +class PxPlaneGeometry : public PxGeometry +{ +public: + PX_INLINE PxPlaneGeometry() : PxGeometry(PxGeometryType::ePLANE) {} + + /** + \brief Returns true if the geometry is valid. + + \return True if the current settings are valid + */ + PX_INLINE bool isValid() const; +}; + + +PX_INLINE bool PxPlaneGeometry::isValid() const +{ + if (mType != PxGeometryType::ePLANE) + return false; + + return true; +} + + +/** \brief creates a transform from a plane equation, suitable for an actor transform for a PxPlaneGeometry + +\param[in] plane the desired plane equation +\return a PxTransform which will transform the plane PxPlane(1,0,0,0) to the specified plane +*/ + +PX_FOUNDATION_API PxTransform PxTransformFromPlaneEquation(const PxPlane& plane); + +/** \brief creates a plane equation from a transform, such as the actor transform for a PxPlaneGeometry + +\param[in] transform the transform +\return the plane +*/ + + +PX_INLINE PxPlane PxPlaneEquationFromTransform(const PxTransform& transform) +{ + return transform.transform(PxPlane(1.f,0.f,0.f,0.f)); +} + + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/geometry/PxSimpleTriangleMesh.h b/sources/PhysX/PhysX/include/geometry/PxSimpleTriangleMesh.h new file mode 100644 index 00000000..643905dd --- /dev/null +++ b/sources/PhysX/PhysX/include/geometry/PxSimpleTriangleMesh.h @@ -0,0 +1,166 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_GEOMUTILS_NX_SIMPLETRIANGLEMESH +#define PX_PHYSICS_GEOMUTILS_NX_SIMPLETRIANGLEMESH +/** \addtogroup geomutils +@{ +*/ + +#include "foundation/PxVec3.h" +#include "foundation/PxFlags.h" +#include "common/PxCoreUtilityTypes.h" +#include "common/PxPhysXCommonConfig.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief Enum with flag values to be used in PxSimpleTriangleMesh::flags. +*/ +struct PxMeshFlag +{ + enum Enum + { + /** + \brief Specifies if the SDK should flip normals. + + The PhysX libraries assume that the face normal of a triangle with vertices [a,b,c] can be computed as: + edge1 = b-a + edge2 = c-a + face_normal = edge1 x edge2. + + Note: This is the same as a counterclockwise winding in a right handed coordinate system or + alternatively a clockwise winding order in a left handed coordinate system. + + If this does not match the winding order for your triangles, raise the below flag. + */ + eFLIPNORMALS = (1<<0), + e16_BIT_INDICES = (1<<1) //!< Denotes the use of 16-bit vertex indices + }; +}; + +/** +\brief collection of set bits defined in PxMeshFlag. + +@see PxMeshFlag +*/ +typedef PxFlags PxMeshFlags; +PX_FLAGS_OPERATORS(PxMeshFlag::Enum,PxU16) + + +/** +\brief A structure describing a triangle mesh. +*/ +class PxSimpleTriangleMesh +{ +public: + + /** + \brief Pointer to first vertex point. + */ + PxBoundedData points; + + /** + \brief Pointer to first triangle. + + Caller may add triangleStrideBytes bytes to the pointer to access the next triangle. + + These are triplets of 0 based indices: + vert0 vert1 vert2 + vert0 vert1 vert2 + vert0 vert1 vert2 + ... + + where vertex is either a 32 or 16 bit unsigned integer. There are numTriangles*3 indices. + + This is declared as a void pointer because it is actually either an PxU16 or a PxU32 pointer. + */ + PxBoundedData triangles; + + /** + \brief Flags bits, combined from values of the enum ::PxMeshFlag + */ + PxMeshFlags flags; + + /** + \brief constructor sets to default. + */ + PX_INLINE PxSimpleTriangleMesh(); + /** + \brief (re)sets the structure to the default. + */ + PX_INLINE void setToDefault(); + /** + \brief returns true if the current settings are valid + */ + PX_INLINE bool isValid() const; +}; + + +PX_INLINE PxSimpleTriangleMesh::PxSimpleTriangleMesh() +{ +} + +PX_INLINE void PxSimpleTriangleMesh::setToDefault() +{ + *this = PxSimpleTriangleMesh(); +} + +PX_INLINE bool PxSimpleTriangleMesh::isValid() const +{ + // Check geometry + if(points.count > 0xffff && flags & PxMeshFlag::e16_BIT_INDICES) + return false; + if(!points.data) + return false; + if(points.stride < sizeof(PxVec3)) //should be at least one point's worth of data + return false; + + // Check topology + // The triangles pointer is not mandatory + if(triangles.data) + { + // Indexed mesh + PxU32 limit = (flags & PxMeshFlag::e16_BIT_INDICES) ? sizeof(PxU16)*3 : sizeof(PxU32)*3; + if(triangles.stride < limit) + return false; + } + return true; +} + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/geometry/PxSphereGeometry.h b/sources/PhysX/PhysX/include/geometry/PxSphereGeometry.h new file mode 100644 index 00000000..b89191d4 --- /dev/null +++ b/sources/PhysX/PhysX/include/geometry/PxSphereGeometry.h @@ -0,0 +1,93 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX_SPHERE_GEOMETRY +#define PX_PHYSICS_NX_SPHERE_GEOMETRY +/** \addtogroup geomutils +@{ +*/ +#include "geometry/PxGeometry.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief A class representing the geometry of a sphere. + +Spheres are defined by their radius. +\note The scaling of the sphere is expected to be baked into this value, there is no additional scaling parameter. +*/ +class PxSphereGeometry : public PxGeometry +{ +public: + PX_INLINE PxSphereGeometry() : PxGeometry(PxGeometryType::eSPHERE), radius(0) {} + PX_INLINE PxSphereGeometry(PxReal ir) : PxGeometry(PxGeometryType::eSPHERE), radius(ir) {} + + /** + \brief Returns true if the geometry is valid. + + \return True if the current settings are valid + + \note A valid sphere has radius > 0. + It is illegal to call PxRigidActor::createShape and PxPhysics::createShape with a sphere that has zero radius. + + @see PxRigidActor::createShape, PxPhysics::createShape + */ + PX_INLINE bool isValid() const; + +public: + + /** + \brief The radius of the sphere. + */ + PxReal radius; +}; + + +PX_INLINE bool PxSphereGeometry::isValid() const +{ + if (mType != PxGeometryType::eSPHERE) + return false; + if (!PxIsFinite(radius)) + return false; + if (radius <= 0.0f) + return false; + + return true; +} + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/geometry/PxTriangle.h b/sources/PhysX/PhysX/include/geometry/PxTriangle.h new file mode 100644 index 00000000..8ccc6d64 --- /dev/null +++ b/sources/PhysX/PhysX/include/geometry/PxTriangle.h @@ -0,0 +1,149 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_GEOMUTILS_PX_TRIANGLE +#define PX_PHYSICS_GEOMUTILS_PX_TRIANGLE +/** \addtogroup geomutils + @{ +*/ + +#include "common/PxPhysXCommonConfig.h" +#include "foundation/PxVec3.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief Triangle class. +*/ +class PxTriangle +{ + public: + /** + \brief Constructor + */ + PX_FORCE_INLINE PxTriangle() {} + + /** + \brief Constructor + + \param[in] p0 Point 0 + \param[in] p1 Point 1 + \param[in] p2 Point 2 + */ + PX_FORCE_INLINE PxTriangle(const PxVec3& p0, const PxVec3& p1, const PxVec3& p2) + { + verts[0] = p0; + verts[1] = p1; + verts[2] = p2; + } + + /** + \brief Copy constructor + + \param[in] triangle Tri to copy + */ + PX_FORCE_INLINE PxTriangle(const PxTriangle& triangle) + { + verts[0] = triangle.verts[0]; + verts[1] = triangle.verts[1]; + verts[2] = triangle.verts[2]; + } + + /** + \brief Destructor + */ + PX_FORCE_INLINE ~PxTriangle() {} + + /** + \brief Assignment operator + */ + PX_FORCE_INLINE void operator=(const PxTriangle& triangle) + { + verts[0] = triangle.verts[0]; + verts[1] = triangle.verts[1]; + verts[2] = triangle.verts[2]; + } + + /** + \brief Compute the normal of the Triangle. + + \param[out] _normal Triangle normal. + */ + PX_FORCE_INLINE void normal(PxVec3& _normal) const + { + _normal = (verts[1]-verts[0]).cross(verts[2]-verts[0]); + _normal.normalize(); + } + + /** + \brief Compute the unnormalized normal of the triangle. + + \param[out] _normal Triangle normal (not normalized). + */ + PX_FORCE_INLINE void denormalizedNormal(PxVec3& _normal) const + { + _normal = (verts[1]-verts[0]).cross(verts[2]-verts[0]); + } + + /** + \brief Compute the area of the triangle. + + \return Area of the triangle. + */ + PX_FORCE_INLINE PxReal area() const + { + const PxVec3& p0 = verts[0]; + const PxVec3& p1 = verts[1]; + const PxVec3& p2 = verts[2]; + return ((p0 - p1).cross(p0 - p2)).magnitude() * 0.5f; + } + + /** + \return Computes a point on the triangle from u and v barycentric coordinates. + */ + PxVec3 pointFromUV(PxReal u, PxReal v) const { return (1.0f-u-v)*verts[0] + u*verts[1] + v*verts[2]; } + + /** + \brief Array of Vertices. + */ + PxVec3 verts[3]; + +}; + + +#if !PX_DOXYGEN +} +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/geometry/PxTriangleMesh.h b/sources/PhysX/PhysX/include/geometry/PxTriangleMesh.h new file mode 100644 index 00000000..6b0eb2ef --- /dev/null +++ b/sources/PhysX/PhysX/include/geometry/PxTriangleMesh.h @@ -0,0 +1,317 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_GEOMUTILS_NX_TRIANGLEMESH +#define PX_PHYSICS_GEOMUTILS_NX_TRIANGLEMESH +/** \addtogroup geomutils +@{ */ + +#include "foundation/PxVec3.h" +#include "foundation/PxBounds3.h" +#include "common/PxPhysXCommonConfig.h" +#include "common/PxBase.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief Enables the dynamic rtree mesh feature. It is recommended to use this feature for scene queries only. +@see PxTriangleMesh::getVerticesForModification +@see PxTriangleMesh::refitBVH +*/ +#define PX_ENABLE_DYNAMIC_MESH_RTREE 1 + +/** +\brief Mesh midphase structure. This enum is used to select the desired acceleration structure for midphase queries + (i.e. raycasts, overlaps, sweeps vs triangle meshes). + + The PxMeshMidPhase::eBVH33 structure is the one used in recent PhysX versions (up to PhysX 3.3). It has great performance and is + supported on all platforms. + + The PxMeshMidPhase::eBVH34 structure is a revisited implementation introduced in PhysX 3.4. It can be significantly faster both + in terms of cooking performance and runtime performance, but it is currently only available on platforms supporting the + SSE2 instuction set. +*/ +struct PxMeshMidPhase +{ + enum Enum + { + eBVH33 = 0, //!< Default midphase mesh structure, as used up to PhysX 3.3 + eBVH34 = 1, //!< New midphase mesh structure, introduced in PhysX 3.4 + + eLAST + }; +}; + +/** +\brief Flags for the mesh geometry properties. + +Used in ::PxTriangleMeshFlags. +*/ +struct PxTriangleMeshFlag +{ + enum Enum + { + e16_BIT_INDICES = (1<<1), //!< The triangle mesh has 16bits vertex indices. + eADJACENCY_INFO = (1<<2) //!< The triangle mesh has adjacency information build. + }; +}; + +/** +\brief collection of set bits defined in PxTriangleMeshFlag. + +@see PxTriangleMeshFlag +*/ +typedef PxFlags PxTriangleMeshFlags; +PX_FLAGS_OPERATORS(PxTriangleMeshFlag::Enum,PxU8) + +/** + +\brief A triangle mesh, also called a 'polygon soup'. + +It is represented as an indexed triangle list. There are no restrictions on the +triangle data. + +To avoid duplicating data when you have several instances of a particular +mesh positioned differently, you do not use this class to represent a +mesh object directly. Instead, you create an instance of this mesh via +the PxTriangleMeshGeometry and PxShape classes. + +

Creation

+ +To create an instance of this class call PxPhysics::createTriangleMesh(), +and release() to delete it. This is only possible +once you have released all of its PxShape instances. + + +

Visualizations:

+\li #PxVisualizationParameter::eCOLLISION_AABBS +\li #PxVisualizationParameter::eCOLLISION_SHAPES +\li #PxVisualizationParameter::eCOLLISION_AXES +\li #PxVisualizationParameter::eCOLLISION_FNORMALS +\li #PxVisualizationParameter::eCOLLISION_EDGES + +@see PxTriangleMeshDesc PxTriangleMeshGeometry PxShape PxPhysics.createTriangleMesh() +*/ + +class PxTriangleMesh : public PxBase +{ + public: + /** + \brief Returns the number of vertices. + \return number of vertices + @see getVertices() + */ + virtual PxU32 getNbVertices() const = 0; + + /** + \brief Returns the vertices. + \return array of vertices + @see getNbVertices() + */ + virtual const PxVec3* getVertices() const = 0; + +#if PX_ENABLE_DYNAMIC_MESH_RTREE + /** + \brief Returns all mesh vertices for modification. + + This function will return the vertices of the mesh so that their positions can be changed in place. + After modifying the vertices you must call refitBVH for the refitting to actually take place. + This function maintains the old mesh topology (triangle indices). + + \return inplace vertex coordinates for each existing mesh vertex. + + \note works only for PxMeshMidPhase::eBVH33 + \note Size of array returned is equal to the number returned by getNbVertices(). + \note This function operates on cooked vertex indices. + \note This means the index mapping and vertex count can be different from what was provided as an input to the cooking routine. + \note To achieve unchanged 1-to-1 index mapping with orignal mesh data (before cooking) please use the following cooking flags: + \note eWELD_VERTICES = 0, eDISABLE_CLEAN_MESH = 1. + \note It is also recommended to make sure that a call to validateTriangleMesh returns true if mesh cleaning is disabled. + @see getNbVertices() + @see refitBVH() + */ + virtual PxVec3* getVerticesForModification() = 0; + + /** + \brief Refits BVH for mesh vertices. + + This function will refit the mesh BVH to correctly enclose the new positions updated by getVerticesForModification. + Mesh BVH will not be reoptimized by this function so significantly different new positions will cause significantly reduced performance. + + \return New bounds for the entire mesh. + + \note works only for PxMeshMidPhase::eBVH33 + \note PhysX does not keep a mapping from the mesh to mesh shapes that reference it. + \note Call PxShape::setGeometry on each shape which references the mesh, to ensure that internal data structures are updated to reflect the new geometry. + \note PxShape::setGeometry does not guarantee correct/continuous behavior when objects are resting on top of old or new geometry. + \note It is also recommended to make sure that a call to validateTriangleMesh returns true if mesh cleaning is disabled. + \note Active edges information will be lost during refit, the rigid body mesh contact generation might not perform as expected. + @see getNbVertices() + @see getVerticesForModification() + */ + virtual PxBounds3 refitBVH() = 0; +#endif // PX_ENABLE_DYNAMIC_MESH_RTREE + + /** + \brief Returns the number of triangles. + \return number of triangles + @see getTriangles() getTrianglesRemap() + */ + virtual PxU32 getNbTriangles() const = 0; + + /** + \brief Returns the triangle indices. + + The indices can be 16 or 32bit depending on the number of triangles in the mesh. + Call getTriangleMeshFlags() to know if the indices are 16 or 32 bits. + + The number of indices is the number of triangles * 3. + + \return array of triangles + @see getNbTriangles() getTriangleMeshFlags() getTrianglesRemap() + */ + virtual const void* getTriangles() const = 0; + + /** + \brief Reads the PxTriangleMesh flags. + + See the list of flags #PxTriangleMeshFlag + + \return The values of the PxTriangleMesh flags. + + @see PxTriangleMesh + */ + virtual PxTriangleMeshFlags getTriangleMeshFlags() const = 0; + + /** + \brief Returns the triangle remapping table. + + The triangles are internally sorted according to various criteria. Hence the internal triangle order + does not always match the original (user-defined) order. The remapping table helps finding the old + indices knowing the new ones: + + remapTable[ internalTriangleIndex ] = originalTriangleIndex + + \return the remapping table (or NULL if 'PxCookingParams::suppressTriangleMeshRemapTable' has been used) + @see getNbTriangles() getTriangles() PxCookingParams::suppressTriangleMeshRemapTable + */ + virtual const PxU32* getTrianglesRemap() const = 0; + + + /** + \brief Decrements the reference count of a triangle mesh and releases it if the new reference count is zero. + + @see PxPhysics.createTriangleMesh() + */ + virtual void release() = 0; + + /** + \brief Returns material table index of given triangle + + This function takes a post cooking triangle index. + + \param[in] triangleIndex (internal) index of desired triangle + \return Material table index, or 0xffff if no per-triangle materials are used + */ + virtual PxMaterialTableIndex getTriangleMaterialIndex(PxTriangleID triangleIndex) const = 0; + + /** + \brief Returns the local-space (vertex space) AABB from the triangle mesh. + + \return local-space bounds + */ + virtual PxBounds3 getLocalBounds() const = 0; + + /** + \brief Returns the reference count for shared meshes. + + At creation, the reference count of the mesh is 1. Every shape referencing this mesh increments the + count by 1. When the reference count reaches 0, and only then, the mesh gets destroyed automatically. + + \return the current reference count. + */ + virtual PxU32 getReferenceCount() const = 0; + + /** + \brief Acquires a counted reference to a triangle mesh. + + This method increases the reference count of the triangle mesh by 1. Decrement the reference count by calling release() + */ + virtual void acquireReference() = 0; + +protected: + PX_INLINE PxTriangleMesh(PxType concreteType, PxBaseFlags baseFlags) : PxBase(concreteType, baseFlags) {} + PX_INLINE PxTriangleMesh(PxBaseFlags baseFlags) : PxBase(baseFlags) {} + virtual ~PxTriangleMesh() {} + + virtual bool isKindOf(const char* name) const { return !::strcmp("PxTriangleMesh", name) || PxBase::isKindOf(name); } +}; + +/** + +\brief A triangle mesh containing the PxMeshMidPhase::eBVH33 structure. + +@see PxMeshMidPhase +*/ +class PxBVH33TriangleMesh : public PxTriangleMesh +{ + public: +protected: + PX_INLINE PxBVH33TriangleMesh(PxType concreteType, PxBaseFlags baseFlags) : PxTriangleMesh(concreteType, baseFlags) {} + PX_INLINE PxBVH33TriangleMesh(PxBaseFlags baseFlags) : PxTriangleMesh(baseFlags) {} + virtual ~PxBVH33TriangleMesh() {} + virtual bool isKindOf(const char* name) const { return !::strcmp("PxBVH33TriangleMesh", name) || PxTriangleMesh::isKindOf(name); } +}; + +/** + +\brief A triangle mesh containing the PxMeshMidPhase::eBVH34 structure. + +@see PxMeshMidPhase +*/ +class PxBVH34TriangleMesh : public PxTriangleMesh +{ + public: +protected: + PX_INLINE PxBVH34TriangleMesh(PxType concreteType, PxBaseFlags baseFlags) : PxTriangleMesh(concreteType, baseFlags) {} + PX_INLINE PxBVH34TriangleMesh(PxBaseFlags baseFlags) : PxTriangleMesh(baseFlags) {} + virtual ~PxBVH34TriangleMesh() {} + virtual bool isKindOf(const char* name) const { return !::strcmp("PxBVH34TriangleMesh", name) || PxTriangleMesh::isKindOf(name); } +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/geometry/PxTriangleMeshGeometry.h b/sources/PhysX/PhysX/include/geometry/PxTriangleMeshGeometry.h new file mode 100644 index 00000000..56f58f79 --- /dev/null +++ b/sources/PhysX/PhysX/include/geometry/PxTriangleMeshGeometry.h @@ -0,0 +1,150 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_NX_TRIANGLEMESH_GEOMETRY +#define PX_PHYSICS_NX_TRIANGLEMESH_GEOMETRY +/** \addtogroup geomutils +@{ +*/ +#include "geometry/PxGeometry.h" +#include "geometry/PxMeshScale.h" +#include "common/PxCoreUtilityTypes.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxTriangleMesh; + + +/** +\brief Flags controlling the simulated behavior of the triangle mesh geometry. + +Used in ::PxMeshGeometryFlags. +*/ +struct PxMeshGeometryFlag +{ + enum Enum + { + eDOUBLE_SIDED = (1<<1) //!< Meshes with this flag set are treated as double-sided. + //!< This flag is currently only used for raycasts and sweeps (it is ignored for overlap queries). + //!< For detailed specifications of this flag for meshes and heightfields please refer to the Geometry Query section of the user guide. + }; +}; + +/** +\brief collection of set bits defined in PxMeshGeometryFlag. + +@see PxMeshGeometryFlag +*/ +typedef PxFlags PxMeshGeometryFlags; +PX_FLAGS_OPERATORS(PxMeshGeometryFlag::Enum,PxU8) + +/** +\brief Triangle mesh geometry class. + +This class unifies a mesh object with a scaling transform, and +lets the combined object be used anywhere a PxGeometry is needed. + +The scaling is a transform along arbitrary axes contained in the scale object. +The vertices of the mesh in geometry (or shape) space is the +PxMeshScale::toMat33() transform, multiplied by the vertex space vertices +in the PxConvexMesh object. +*/ +class PxTriangleMeshGeometry : public PxGeometry +{ +public: + /** + \brief Default constructor. + + Creates an empty object with a NULL mesh and identity scale. + */ + PX_INLINE PxTriangleMeshGeometry() : + PxGeometry (PxGeometryType::eTRIANGLEMESH), + triangleMesh(NULL) + {} + + /** + \brief Constructor. + \param[in] mesh Mesh pointer. May be NULL, though this will not make the object valid for shape construction. + \param[in] scaling Scale factor. + \param[in] flags Mesh flags. + \ + */ + PX_INLINE PxTriangleMeshGeometry( PxTriangleMesh* mesh, + const PxMeshScale& scaling = PxMeshScale(), + PxMeshGeometryFlags flags = PxMeshGeometryFlags()) : + PxGeometry (PxGeometryType::eTRIANGLEMESH), + scale (scaling), + meshFlags (flags), + triangleMesh(mesh) + {} + + /** + \brief Returns true if the geometry is valid. + + \return True if the current settings are valid for shape creation. + + \note A valid triangle mesh has a positive scale value in each direction (scale.scale.x > 0, scale.scale.y > 0, scale.scale.z > 0). + It is illegal to call PxRigidActor::createShape and PxPhysics::createShape with a triangle mesh that has zero extents in any direction. + + @see PxRigidActor::createShape, PxPhysics::createShape + */ + PX_INLINE bool isValid() const; + +public: + PxMeshScale scale; //!< The scaling transformation. + PxMeshGeometryFlags meshFlags; //!< Mesh flags. + PxPadding<3> paddingFromFlags; //!< padding for mesh flags + PxTriangleMesh* triangleMesh; //!< A reference to the mesh object. +}; + + +PX_INLINE bool PxTriangleMeshGeometry::isValid() const +{ + if(mType != PxGeometryType::eTRIANGLEMESH) + return false; + if(!scale.scale.isFinite() || !scale.rotation.isUnit()) + return false; + if(!scale.isValidForTriangleMesh()) + return false; + if(!triangleMesh) + return false; + + return true; +} + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/geomutils/GuContactBuffer.h b/sources/PhysX/PhysX/include/geomutils/GuContactBuffer.h new file mode 100644 index 00000000..78673579 --- /dev/null +++ b/sources/PhysX/PhysX/include/geomutils/GuContactBuffer.h @@ -0,0 +1,131 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef GU_CONTACTBUFFER_H +#define GU_CONTACTBUFFER_H + +#include "geomutils/GuContactPoint.h" +#include "PxPhysXConfig.h" +#include "PxContact.h" + +namespace physx +{ +namespace Gu +{ + + struct NarrowPhaseParams + { + PX_FORCE_INLINE NarrowPhaseParams(PxReal contactDistance, PxReal meshContactMargin, PxReal toleranceLength) : + mContactDistance(contactDistance), + mMeshContactMargin(meshContactMargin), + mToleranceLength(toleranceLength) {} + + PxReal mContactDistance; + PxReal mMeshContactMargin; // PT: Margin used to generate mesh contacts. Temp & unclear, should be removed once GJK is default path. + PxReal mToleranceLength; // PT: copy of PxTolerancesScale::length + }; + +//sizeof(SavedContactData)/sizeof(PxU32) = 17, 1088/17 = 64 triangles in the local array +#define LOCAL_CONTACTS_SIZE 1088 + +class ContactBuffer +{ +public: + + static const PxU32 MAX_CONTACTS = 64; + + Gu::ContactPoint contacts[MAX_CONTACTS]; + PxU32 count; + PxU32 pad; + + PX_FORCE_INLINE void reset() + { + count = 0; + } + + PX_FORCE_INLINE bool contact(const PxVec3& worldPoint, + const PxVec3& worldNormalIn, + PxReal separation, + PxU32 faceIndex1 = PXC_CONTACT_NO_FACE_INDEX + ) + { + PX_ASSERT(PxAbs(worldNormalIn.magnitude()-1)<1e-3f); + + if(count>=MAX_CONTACTS) + return false; + + Gu::ContactPoint& p = contacts[count++]; + p.normal = worldNormalIn; + p.point = worldPoint; + p.separation = separation; + p.internalFaceIndex1= faceIndex1; + return true; + } + + PX_FORCE_INLINE bool contact(const PxVec3& worldPoint, + const PxVec3& worldNormalIn, + PxReal separation, + PxU16 internalUsage, + PxU32 faceIndex1 = PXC_CONTACT_NO_FACE_INDEX + ) + { + PX_ASSERT(PxAbs(worldNormalIn.magnitude() - 1)<1e-3f); + + if (count >= MAX_CONTACTS) + return false; + + Gu::ContactPoint& p = contacts[count++]; + p.normal = worldNormalIn; + p.point = worldPoint; + p.separation = separation; + p.internalFaceIndex1 = faceIndex1; + p.forInternalUse = internalUsage; + return true; + } + + PX_FORCE_INLINE bool contact(const Gu::ContactPoint & pt) + { + if(count>=MAX_CONTACTS) + return false; + contacts[count++] = pt; + return true; + } + + PX_FORCE_INLINE Gu::ContactPoint* contact() + { + if(count>=MAX_CONTACTS) + return NULL; + return &contacts[count++]; + } +}; + +} +} + +#endif diff --git a/sources/PhysX/PhysX/include/geomutils/GuContactPoint.h b/sources/PhysX/PhysX/include/geomutils/GuContactPoint.h new file mode 100644 index 00000000..33f851d6 --- /dev/null +++ b/sources/PhysX/PhysX/include/geomutils/GuContactPoint.h @@ -0,0 +1,109 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef GU_CONTACT_POINT_H +#define GU_CONTACT_POINT_H + +/** \addtogroup geomutils +@{ +*/ + +#include "foundation/PxVec3.h" + +namespace physx +{ +namespace Gu +{ + +struct ContactPoint +{ + /** + \brief The normal of the contacting surfaces at the contact point. + + For two shapes s0 and s1, the normal points in the direction that s0 needs to move in to resolve the contact with s1. + */ + PX_ALIGN(16, PxVec3 normal); + /** + \brief The separation of the shapes at the contact point. A negative separation denotes a penetration. + */ + PxReal separation; + + /** + \brief The point of contact between the shapes, in world space. + */ + PX_ALIGN(16, PxVec3 point); + + /** + \brief The max impulse permitted at this point + */ + PxReal maxImpulse; + + PX_ALIGN(16, PxVec3 targetVel); + + /** + \brief The static friction coefficient + */ + PxReal staticFriction; + + /** + \brief Material flags for this contact (eDISABLE_FRICTION, eDISABLE_STRONG_FRICTION). @see PxMaterialFlag + */ + PxU8 materialFlags; + + /** + \brief internal structure used for internal use only + */ + PxU16 forInternalUse; + + /** + \brief The surface index of shape 1 at the contact point. This is used to identify the surface material. + + \note This field is only supported by triangle meshes and heightfields, else it will be set to PXC_CONTACT_NO_FACE_INDEX. + \note This value must be directly after internalFaceIndex0 in memory + */ + + PxU32 internalFaceIndex1; + + /** + \brief The dynamic friction coefficient + */ + PxReal dynamicFriction; + /** + \brief The restitution coefficient + */ + PxReal restitution; + +}; + +} + +} + +/** @} */ +#endif diff --git a/sources/PhysX/PhysX/include/gpu/PxGpu.h b/sources/PhysX/PhysX/include/gpu/PxGpu.h new file mode 100644 index 00000000..60210a6b --- /dev/null +++ b/sources/PhysX/PhysX/include/gpu/PxGpu.h @@ -0,0 +1,96 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. + +#ifndef PX_GPU_H +#define PX_GPU_H + +#include "PxPhysXConfig.h" + + +#if PX_SUPPORT_GPU_PHYSX + +#include "cudamanager/PxCudaContextManager.h" +#include "cudamanager/PxCudaMemoryManager.h" +#include "foundation/Px.h" +#include "foundation/PxPreprocessor.h" +#include "common/PxPhysXCommonConfig.h" +#include "PxFoundation.h" + +/** +\brief PxGpuLoadHook + +This is a helper class for loading the PhysXGpu dll. +If a PhysXGpu dll with a non-default file name needs to be loaded, +PxGpuLoadHook can be sub-classed to provide the custom filenames. + +Once the names are set, the instance must be set for use by PhysX.dll using PxSetPhysXGpuLoadHook(), + +@see PxSetPhysXGpuLoadHook() +*/ +class PxGpuLoadHook +{ +public: + PxGpuLoadHook() {} + virtual ~PxGpuLoadHook() {} + + virtual const char* getPhysXGpuDllName() const = 0; + +protected: +private: +}; + +/** +\brief Sets GPU load hook instance for PhysX dll. + +\param[in] hook GPU load hook. + +@see PxGpuLoadHook +*/ +PX_C_EXPORT PX_PHYSX_CORE_API void PX_CALL_CONV PxSetPhysXGpuLoadHook(const PxGpuLoadHook* hook); + +/** + * \brief Ask the NVIDIA control panel which GPU has been selected for use by + * PhysX. Returns -1 if no PhysX capable GPU is found or GPU PhysX has + * been disabled. + */ +PX_C_EXPORT PX_PHYSX_CORE_API int PX_CALL_CONV PxGetSuggestedCudaDeviceOrdinal(physx::PxErrorCallback& errc); + +/** + * \brief Allocate a CUDA Context manager, complete with heaps. + * You only need one CUDA context manager per GPU device you intend to use for + * CUDA tasks. + \param[in] foundation PhysXFoundation instance. + \param[in] desc Cuda context manager desc. + \param[in] profilerCallback PhysX profiler callback instance. + + @see PxGetProfilerCallback() + */ +PX_C_EXPORT PX_PHYSX_CORE_API physx::PxCudaContextManager* PX_CALL_CONV PxCreateCudaContextManager(physx::PxFoundation& foundation, const physx::PxCudaContextManagerDesc& desc, physx::PxProfilerCallback* profilerCallback = NULL); + +#endif // PX_SUPPORT_GPU_PHYSX + +#endif // PX_GPU_H diff --git a/sources/PhysX/PhysX/include/pvd/PxPvd.h b/sources/PhysX/PhysX/include/pvd/PxPvd.h new file mode 100644 index 00000000..08b4aaba --- /dev/null +++ b/sources/PhysX/PhysX/include/pvd/PxPvd.h @@ -0,0 +1,178 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PXPVDSDK_PXPVD_H +#define PXPVDSDK_PXPVD_H + +/** \addtogroup pvd +@{ +*/ +#include "foundation/PxFlags.h" +#include "foundation/PxProfiler.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxFoundation; +class PxPvdTransport; + +/** +\brief types of instrumentation that PVD can do. +*/ +struct PxPvdInstrumentationFlag +{ + enum Enum + { + /** + \brief Send debugging information to PVD. + + This information is the actual object data of the rigid statics, shapes, + articulations, etc. Sending this information has a noticeable impact on + performance and thus this flag should not be set if you want an accurate + performance profile. + */ + eDEBUG = 1 << 0, + + /** + \brief Send profile information to PVD. + + This information populates PVD's profile view. It has (at this time) negligible + cost compared to Debug information and makes PVD *much* more useful so it is quite + highly recommended. + + This flag works together with a PxCreatePhysics parameter. + Using it allows the SDK to send profile events to PVD. + */ + ePROFILE = 1 << 1, + + /** + \brief Send memory information to PVD. + + The PVD sdk side hooks into the Foundation memory controller and listens to + allocation/deallocation events. This has a noticable hit on the first frame, + however, this data is somewhat compressed and the PhysX SDK doesn't allocate much + once it hits a steady state. This information also has a fairly negligible + impact and thus is also highly recommended. + + This flag works together with a PxCreatePhysics parameter, + trackOutstandingAllocations. Using both of them together allows users to have + an accurate view of the overall memory usage of the simulation at the cost of + a hashtable lookup per allocation/deallocation. Again, PhysX makes a best effort + attempt not to allocate or deallocate during simulation so this hashtable lookup + tends to have no effect past the first frame. + + Sending memory information without tracking outstanding allocations means that + PVD will accurate information about the state of the memory system before the + actual connection happened. + */ + eMEMORY = 1 << 2, + + eALL = (eDEBUG | ePROFILE | eMEMORY) + }; +}; + +/** +\brief Bitfield that contains a set of raised flags defined in PxPvdInstrumentationFlag. + +@see PxPvdInstrumentationFlag +*/ +typedef PxFlags PxPvdInstrumentationFlags; +PX_FLAGS_OPERATORS(PxPvdInstrumentationFlag::Enum, uint8_t) + +/** +\brief PxPvd is the top-level class for the PVD framework, and the main customer interface for PVD +configuration.It is a singleton class, instantiated and owned by the application. +*/ +class PxPvd : public physx::PxProfilerCallback +{ + public: + /** + Connects the SDK to the PhysX Visual Debugger application. + \param transport transport for pvd captured data. + \param flags Flags to set. + return True if success + */ + virtual bool connect(PxPvdTransport& transport, PxPvdInstrumentationFlags flags) = 0; + + /** + Disconnects the SDK from the PhysX Visual Debugger application. + If we are still connected, this will kill the entire debugger connection. + */ + virtual void disconnect() = 0; + + /** + * Return if connection to PVD is created. + \param useCachedStatus + 1> When useCachedStaus is false, isConnected() checks the lowlevel network status. + This can be slow because it needs to lock the lowlevel network stream. If isConnected() is + called frequently, the expense of locking can be significant. + 2> When useCachedStatus is true, isConnected() checks the highlevel cached status with atomic access. + It is faster than locking, but the status may be different from the lowlevel network with latency of up to + one frame. + The reason for this is that the cached status is changed inside socket listener, which is not + called immediately when the lowlevel connection status changes. + */ + virtual bool isConnected(bool useCachedStatus = true) = 0; + + /** + returns the PVD data transport + returns NULL if no transport is present. + */ + virtual PxPvdTransport* getTransport() = 0; + + /** + Retrieves the PVD flags. See PxPvdInstrumentationFlags. + */ + virtual PxPvdInstrumentationFlags getInstrumentationFlags() = 0; + + /** + \brief Releases the pvd instance. + */ + virtual void release() = 0; + + protected: + virtual ~PxPvd() + { + } +}; + +/** + \brief Create a pvd instance. + \param foundation is the foundation instance that stores the allocator and error callbacks. +*/ +PX_C_EXPORT PxPvd* PX_CALL_CONV PxCreatePvd(PxFoundation& foundation); + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif // PXPVDSDK_PXPVD_H diff --git a/sources/PhysX/PhysX/include/pvd/PxPvdSceneClient.h b/sources/PhysX/PhysX/include/pvd/PxPvdSceneClient.h new file mode 100644 index 00000000..2db2e073 --- /dev/null +++ b/sources/PhysX/PhysX/include/pvd/PxPvdSceneClient.h @@ -0,0 +1,142 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_PVD_SCENE_CLIENT_H +#define PX_PVD_SCENE_CLIENT_H + +/** \addtogroup pvd +@{ +*/ + +#include "foundation/PxFlags.h" + +namespace physx +{ + namespace pvdsdk + { + class PvdClient; + struct PvdDebugPoint; + struct PvdDebugLine; + struct PvdDebugTriangle; + struct PvdDebugText; + } +} + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief PVD scene Flags. They are disabled by default, and only works if PxPvdInstrumentationFlag::eDEBUG is set. +*/ +struct PxPvdSceneFlag +{ + enum Enum + { + eTRANSMIT_CONTACTS = (1 << 0), //! Transmits contact stream to PVD. + eTRANSMIT_SCENEQUERIES = (1 << 1), //! Transmits scene query stream to PVD. + eTRANSMIT_CONSTRAINTS = (1 << 2) //! Transmits constraints visualize stream to PVD. + }; +}; + +/** +\brief Bitfield that contains a set of raised flags defined in PxPvdSceneFlag. + +@see PxPvdSceneFlag +*/ +typedef PxFlags PxPvdSceneFlags; +PX_FLAGS_OPERATORS(PxPvdSceneFlag::Enum, PxU8) + +/** +\brief Special client for PxScene. +It provides access to the PxPvdSceneFlag. +It also provides simple user debug services that associated scene position such as immediate rendering and camera updates. +*/ +class PxPvdSceneClient +{ + public: + /** + Sets the PVD flag. See PxPvdSceneFlag. + \param flag Flag to set. + \param value value the flag gets set to. + */ + virtual void setScenePvdFlag(PxPvdSceneFlag::Enum flag, bool value) = 0; + + /** + Sets the PVD flags. See PxPvdSceneFlags. + \param flags Flags to set. + */ + virtual void setScenePvdFlags(PxPvdSceneFlags flags) = 0; + + /** + Retrieves the PVD flags. See PxPvdSceneFlags. + */ + virtual PxPvdSceneFlags getScenePvdFlags() const = 0; + + /** + update camera on PVD application's render window + */ + virtual void updateCamera(const char* name, const PxVec3& origin, const PxVec3& up, const PxVec3& target) = 0; + + /** + draw points on PVD application's render window + */ + virtual void drawPoints(const physx::pvdsdk::PvdDebugPoint* points, PxU32 count) = 0; + + /** + draw lines on PVD application's render window + */ + virtual void drawLines(const physx::pvdsdk::PvdDebugLine* lines, PxU32 count) = 0; + + /** + draw triangles on PVD application's render window + */ + virtual void drawTriangles(const physx::pvdsdk::PvdDebugTriangle* triangles, PxU32 count) = 0; + + /** + draw text on PVD application's render window + */ + virtual void drawText(const physx::pvdsdk::PvdDebugText& text) = 0; + + /** + get the underlying client, for advanced users + */ + virtual physx::pvdsdk::PvdClient* getClientInternal() = 0; + +protected: + virtual ~PxPvdSceneClient(){} +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif // PX_PVD_SCENE_CLIENT_H diff --git a/sources/PhysX/PhysX/include/pvd/PxPvdTransport.h b/sources/PhysX/PhysX/include/pvd/PxPvdTransport.h new file mode 100644 index 00000000..169ec23d --- /dev/null +++ b/sources/PhysX/PhysX/include/pvd/PxPvdTransport.h @@ -0,0 +1,129 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PXPVDSDK_PXPVDTRANSPORT_H +#define PXPVDSDK_PXPVDTRANSPORT_H + +/** \addtogroup pvd +@{ +*/ +#include "foundation/PxErrors.h" +#include "foundation/PxFlags.h" +#include "pvd/PxPvd.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief PxPvdTransport is an interface representing the data transport mechanism. +This class defines all services associated with the transport: configuration, connection, reading, writing etc. +It is owned by the application, and can be realized as a file or a socket (using one-line PxDefault<...> methods in +PhysXExtensions) or in a custom implementation. This is a class that is intended for use by PVD, not by the +application, the application entry points are PxPvd and PvdClient. +*/ + +class PxPvdTransport +{ + public: + // connect, isConnected, disconnect, read, write, flush + + /** + Connects to the Visual Debugger application. + return True if success + */ + virtual bool connect() = 0; + + /** + Disconnects from the Visual Debugger application. + If we are still connected, this will kill the entire debugger connection. + */ + virtual void disconnect() = 0; + + /** + * Return if connection to PVD is created. + */ + virtual bool isConnected() = 0; + + /** + * write bytes to the other endpoint of the connection. should lock before witre. If an error occurs + * this connection will assume to be dead. + */ + virtual bool write(const uint8_t* inBytes, uint32_t inLength) = 0; + + /* + lock this transport and return it + */ + virtual PxPvdTransport& lock() = 0; + + /* + unlock this transport + */ + virtual void unlock() = 0; + + /** + * send any data and block until we know it is at least on the wire. + */ + virtual void flush() = 0; + + /** + * Return size of written data. + */ + virtual uint64_t getWrittenDataSize() = 0; + + virtual void release() = 0; + + protected: + virtual ~PxPvdTransport() + { + } +}; + +/** + \brief Create a default socket transport. + \param host host address of the pvd application. + \param port ip port used for pvd, should same as the port setting in pvd application. + \param timeoutInMilliseconds timeout when connect to pvd host. +*/ +PX_C_EXPORT PxPvdTransport* PX_CALL_CONV +PxDefaultPvdSocketTransportCreate(const char* host, int port, unsigned int timeoutInMilliseconds); + +/** + \brief Create a default file transport. + \param name full path filename used save captured pvd data, or NULL for a fake/test file transport. +*/ +PX_C_EXPORT PxPvdTransport* PX_CALL_CONV PxDefaultPvdFileTransportCreate(const char* name); + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif // PXPVDSDK_PXPVDTRANSPORT_H diff --git a/sources/PhysX/PhysX/include/solver/PxSolverDefs.h b/sources/PhysX/PhysX/include/solver/PxSolverDefs.h new file mode 100644 index 00000000..f93b6835 --- /dev/null +++ b/sources/PhysX/PhysX/include/solver/PxSolverDefs.h @@ -0,0 +1,443 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_SOLVER_DEFS_H +#define PX_SOLVER_DEFS_H + +#include "PxPhysXConfig.h" +#include "foundation/PxVec3.h" +#include "foundation/PxMat33.h" +#include "foundation/PxTransform.h" +#include "PxConstraintDesc.h" +#include "geomutils/GuContactPoint.h" + +#if PX_VC +#pragma warning(push) +#pragma warning(disable : 4324) // structure was padded due to alignment +#endif + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +struct PxTGSSolverBodyVel; + +namespace Dy +{ + class ArticulationV; + typedef size_t ArticulationLinkHandle; +} + +namespace Sc +{ + class ShapeInteraction; +} + +struct PxSolverBody +{ + PX_ALIGN(16, PxVec3) linearVelocity; //!< Delta linear velocity computed by the solver + PxU16 maxSolverNormalProgress; //!< Progress counter used by constraint batching and parallel island solver. + PxU16 maxSolverFrictionProgress; //!< Progress counter used by constraint batching and parallel island solver. + + PxVec3 angularState; //!< Delta angular velocity state computed by the solver. + + PxU32 solverProgress; //!< Progress counter used by constraint batching and parallel island solver + + PxSolverBody() : linearVelocity(0.f), maxSolverNormalProgress(0), maxSolverFrictionProgress(0), angularState(0), solverProgress(0) + { + } +}; + +PX_COMPILE_TIME_ASSERT(sizeof(PxSolverBody) == 32); + +struct PxSolverBodyData +{ + PX_ALIGN(16, PxVec3 linearVelocity); //!< 12 Pre-solver linear velocity + PxReal invMass; //!< 16 inverse mass + PxVec3 angularVelocity; //!< 28 Pre-solver angular velocity + PxReal reportThreshold; //!< 32 contact force threshold + PxMat33 sqrtInvInertia; //!< 68 inverse inertia in world space + PxReal penBiasClamp; //!< 72 the penetration bias clamp + PxU32 nodeIndex; //!< 76 the node idx of this solverBodyData. Used by solver to reference between solver bodies and island bodies. Not required by immediate mode + PxReal maxContactImpulse; //!< 80 the max contact impulse + PxTransform body2World; //!< 108 the body's transform + PxU16 lockFlags; //!< 110 lock flags + PxU16 pad; //!< 112 pad + + PX_FORCE_INLINE PxReal projectVelocity(const PxVec3& lin, const PxVec3& ang) const + { + return linearVelocity.dot(lin) + angularVelocity.dot(ang); + } +}; + +//---------------------------------- +/* +* A header that defines the size of a specific batch of constraints (of same type and without dependencies) +*/ +struct PxConstraintBatchHeader +{ + PxU32 startIndex; //!< Start index for this batch + PxU16 stride; //!< Number of constraints in this batch (range: 1-4) + PxU16 constraintType; //!< The type of constraint this batch references +}; + +struct PxSolverConstraintDesc +{ + static const PxU16 NO_LINK = 0xffff; + + enum ConstraintType + { + eCONTACT_CONSTRAINT, //!< Defines this pair is a contact constraint + eJOINT_CONSTRAINT //!< Defines this pair is a joint constraint + }; + + union + { + PxSolverBody* bodyA; //!< bodyA pointer + PxTGSSolverBodyVel* tgsBodyA; //!< bodyA pointer + Dy::ArticulationV* articulationA; //!< Articulation pointer for body A + + }; + + union + { + PxSolverBody* bodyB; //!< BodyB pointer + PxTGSSolverBodyVel* tgsBodyB; //!< BodyB pointer + Dy::ArticulationV* articulationB; //!< Articulation pointer for body B + }; + PxU16 linkIndexA; //!< Link index defining which link in Articulation A this constraint affects. If not an articulation, must be NO_LINK + PxU16 linkIndexB; //!< Link index defining which link in Articulation B this constraint affects. If not an articulation, must be NO_LINK. + PxU32 bodyADataIndex; //!< Body A's index into the SolverBodyData array + PxU32 bodyBDataIndex; //!< Body B's index into the SolverBodyData array + PxU16 writeBackLengthOver4; //!< writeBackLength/4, max writeback length is 256K, allows PxSolverConstraintDesc to fit in 32 bytes + PxU16 constraintLengthOver16; //!< constraintLength/16, max constraint length is 1MB, allows PxSolverConstraintDesc to fit in 32 bytes + PxU8* constraint; //!< Pointer to the constraint rows to be solved + void* writeBack; //!< Pointer to the writeback structure results for this given constraint are to be written to +}; + +struct PxSolverConstraintPrepDescBase +{ + enum BodyState + { + eDYNAMIC_BODY = 1 << 0, + eSTATIC_BODY = 1 << 1, + eKINEMATIC_BODY = 1 << 2, + eARTICULATION = 1 << 3 + }; + + PxConstraintInvMassScale invMassScales; //!< In: The local mass scaling for this pair. + + PxSolverConstraintDesc* desc; //!< Output: The PxSolverConstraintDesc filled in by contact prep + + const PxSolverBody* body0; //!< In: The first body. Stores velocity information. Unused unless contact involves articulations. + const PxSolverBody* body1; //!< In: The second body. Stores velocity information. Unused unless contact involves articulations. + + const PxSolverBodyData* data0; //!< In: The first PxSolverBodyData. Stores mass and miscellaneous information for the first body. + const PxSolverBodyData* data1; //!< In: The second PxSolverBodyData. Stores mass and miscellaneous information for the second body + + PxTransform bodyFrame0; //!< In: The world-space transform of the first body. + PxTransform bodyFrame1; //!< In: The world-space transform of the second body. + + BodyState bodyState0; //!< In: Defines what kind of actor the first body is + BodyState bodyState1; //!< In: Defines what kind of actor the second body is +}; + +struct PxSolverConstraintPrepDesc : public PxSolverConstraintPrepDescBase +{ + PX_ALIGN(16, Px1DConstraint* rows); //!< The start of the constraint rows + PxU32 numRows; //!< The number of rows + + PxReal linBreakForce, angBreakForce; //!< Break forces + PxReal minResponseThreshold; //!< The minimum response threshold + void* writeback; //!< Pointer to constraint writeback structure. Reports back joint breaking. If not required, set to NULL. + bool disablePreprocessing; //!< Disable joint pre-processing. Pre-processing can improve stability but under certain circumstances, e.g. when some invInertia rows are zero/almost zero, can cause instabilities. + bool improvedSlerp; //!< Use improved slerp model + bool driveLimitsAreForces; //!< Indicates whether drive limits are forces + bool extendedLimits; //!< Indicates whether we want to use extended limits + + PxVec3 body0WorldOffset; //!< Body0 world offset +}; + +struct PxSolverContactDesc : public PxSolverConstraintPrepDescBase +{ + PX_ALIGN(16, Sc::ShapeInteraction* shapeInteraction); //!< Pointer to share interaction. Used for force threshold reports in solver. Set to NULL if using immediate mode. + Gu::ContactPoint* contacts; //!< The start of the contacts for this pair + PxU32 numContacts; //!< The total number of contacs this pair references. + + bool hasMaxImpulse; //!< Defines whether this pairs has maxImpulses clamping enabled + bool disableStrongFriction; //!< Defines whether this pair disables strong friction (sticky friction correlation) + bool hasForceThresholds; //!< Defines whether this pair requires force thresholds + + PxReal restDistance; //!< A distance at which the solver should aim to hold the bodies separated. Default is 0 + PxReal maxCCDSeparation; //!< A distance used to configure speculative CCD behavior. Default is PX_MAX_F32. Set internally in PhysX for bodies with eENABLE_SPECULATIVE_CCD on. Do not set directly! + + PxU8* frictionPtr; //!< InOut: Friction patch correlation data. Set each frame by solver. Can be retained for improved behaviour or discarded each frame. + PxU8 frictionCount; //!< The total number of friction patches in this pair + + PxReal* contactForces; //!< Out: A buffer for the solver to write applied contact forces to. + + PxU32 startFrictionPatchIndex; //!< Start index of friction patch in the correlation buffer. Set by friction correlation + PxU32 numFrictionPatches; //!< Total number of friction patches in this pair. Set by friction correlation + + PxU32 startContactPatchIndex; //!< The start index of this pair's contact patches in the correlation buffer. For internal use only + PxU16 numContactPatches; //!< Total number of contact patches. + PxU16 axisConstraintCount; //!< Axis constraint count. Defines how many constraint rows this pair has produced. Useful for statistical purposes. + + PxU8 pad[16 - sizeof(void*)]; +}; + +class PxConstraintAllocator +{ +public: + /** + \brief Allocates constraint data. It is the application's responsibility to release this memory after PxSolveConstraints has completed. + \param[in] byteSize Allocation size in bytes + \return the allocated memory. This address must be 16-byte aligned. + */ + virtual PxU8* reserveConstraintData(const PxU32 byteSize) = 0; + + /** + \brief Allocates friction data. Friction data can be retained by the application for a given pair and provided as an input to PxSolverContactDesc to improve simulation stability. + It is the application's responsibility to release this memory. If this memory is released, the application should ensure it does not pass pointers to this memory to PxSolverContactDesc. + \param[in] byteSize Allocation size in bytes + \return the allocated memory. This address must be 4-byte aligned. + */ + virtual PxU8* reserveFrictionData(const PxU32 byteSize) = 0; + + virtual ~PxConstraintAllocator() {} +}; + +struct PxArticulationAxis +{ + enum Enum + { + eTWIST = 0, + eSWING1 = 1, + eSWING2 = 2, + eX = 3, + eY = 4, + eZ = 5, + eCOUNT = 6 + }; +}; + +PX_FLAGS_OPERATORS(PxArticulationAxis::Enum, PxU8) + +struct PxArticulationMotion +{ + enum Enum + { + eLOCKED = 0, + eLIMITED = 1, + eFREE = 2 + }; +}; + +typedef PxFlags PxArticulationMotions; +PX_FLAGS_OPERATORS(PxArticulationMotion::Enum, PxU8) + +struct PxArticulationJointType +{ + enum Enum + { + ePRISMATIC = 0, + eREVOLUTE = 1, + eSPHERICAL = 2, + eFIX = 3, + eUNDEFINED = 4 + }; +}; + +struct PxArticulationFlag +{ + enum Enum + { + eFIX_BASE = (1 << 0), + eDRIVE_LIMITS_ARE_FORCES = (1<<1) + }; +}; + +typedef PxFlags PxArticulationFlags; +PX_FLAGS_OPERATORS(PxArticulationFlag::Enum, PxU8) + +struct PxArticulationDriveType +{ + enum Enum + { + eFORCE = 0, + eACCELERATION = 1, + eTARGET = 2, + eVELOCITY = 3, + eNONE = 4 + }; +}; + +struct PxArticulationLimit +{ + PxReal low, high; +}; + +struct PxArticulationDrive +{ + PxReal stiffness, damping, maxForce; + PxArticulationDriveType::Enum driveType; +}; + + +struct PxTGSSolverBodyVel +{ + PX_ALIGN(16, PxVec3) linearVelocity; //12 + PxU16 nbStaticInteractions; //14 Used to accumulate the number of static interactions + PxU16 maxDynamicPartition; //16 Used to accumualte the max partition of dynamic interactions + PxVec3 angularVelocity; //28 + PxU32 partitionMask; //32 Used in partitioning as a bit-field + PxVec3 deltaAngDt; //44 + PxReal maxAngVel; //48 + PxVec3 deltaLinDt; //60 + PxU16 lockFlags; //62 + bool isKinematic; //63 + PxU8 pad; //64 + + PX_FORCE_INLINE PxReal projectVelocity(const PxVec3& lin, const PxVec3& ang) const + { + return linearVelocity.dot(lin) + angularVelocity.dot(ang); + } + +}; + +//Needed only by prep, integration and 1D constraints +struct PxTGSSolverBodyTxInertia +{ + PxTransform deltaBody2World; + PxMat33 sqrtInvInertia; +}; + +struct PxTGSSolverBodyData +{ + PX_ALIGN(16, PxVec3) originalLinearVelocity; + PxReal maxContactImpulse; + PxVec3 originalAngularVelocity; + PxReal penBiasClamp; + + PxReal invMass; + PxU32 nodeIndex; + PxReal reportThreshold; + PxU32 pad; + + PxReal projectVelocity(const PxVec3& linear, const PxVec3& angular) const + { + return originalLinearVelocity.dot(linear) + originalAngularVelocity.dot(angular); + } +}; + +struct PxTGSSolverConstraintPrepDescBase +{ + PxConstraintInvMassScale invMassScales; //!< In: The local mass scaling for this pair. + + PxSolverConstraintDesc* desc; //!< Output: The PxSolverConstraintDesc filled in by contact prep + + const PxTGSSolverBodyVel* body0; //!< In: The first body. Stores velocity information. Unused unless contact involves articulations. + const PxTGSSolverBodyVel *body1; //!< In: The second body. Stores velocity information. Unused unless contact involves articulations. + + const PxTGSSolverBodyTxInertia* body0TxI; + const PxTGSSolverBodyTxInertia* body1TxI; + + const PxTGSSolverBodyData* bodyData0; + const PxTGSSolverBodyData* bodyData1; + + PxTransform bodyFrame0; //!< In: The world-space transform of the first body. + PxTransform bodyFrame1; //!< In: The world-space transform of the second body. + + PxSolverContactDesc::BodyState bodyState0; //!< In: Defines what kind of actor the first body is + PxSolverContactDesc::BodyState bodyState1; //!< In: Defines what kind of actor the second body is + +}; + +struct PxTGSSolverConstraintPrepDesc : public PxTGSSolverConstraintPrepDescBase +{ + Px1DConstraint* rows; //!< The start of the constraint rows + PxU32 numRows; //!< The number of rows + + PxReal linBreakForce, angBreakForce; //!< Break forces + PxReal minResponseThreshold; //!< The minimum response threshold + void* writeback; //!< Pointer to constraint writeback structure. Reports back joint breaking. If not required, set to NULL. + bool disablePreprocessing; //!< Disable joint pre-processing. Pre-processing can improve stability but under certain circumstances, e.g. when some invInertia rows are zero/almost zero, can cause instabilities. + bool improvedSlerp; //!< Use improved slerp model + bool driveLimitsAreForces; //!< Indicates whether drive limits are forces + bool extendedLimits; //!< Indiciates whether extended limits are used + + PxVec3 body0WorldOffset; //!< Body0 world offset + PxVec3 cA2w; //!< Location of anchor point A in world space + PxVec3 cB2w; //!< Location of anchor point B in world space +}; + + +struct PxTGSSolverContactDesc : public PxTGSSolverConstraintPrepDescBase +{ + + Sc::ShapeInteraction* shapeInteraction; //!< Pointer to share interaction. Used for force threshold reports in solver. Set to NULL if using immediate mode. + Gu::ContactPoint* contacts; //!< The start of the contacts for this pair + PxU32 numContacts; //!< The total number of contacs this pair references. + + bool hasMaxImpulse; //!< Defines whether this pairs has maxImpulses clamping enabled + bool disableStrongFriction; //!< Defines whether this pair disables strong friction (sticky friction correlation) + bool hasForceThresholds; //!< Defines whether this pair requires force thresholds + + PxReal restDistance; //!< A distance at which the solver should aim to hold the bodies separated. Default is 0 + PxReal maxCCDSeparation; //!< A distance used to configure speculative CCD behavior. Default is PX_MAX_F32. Set internally in PhysX for bodies with eENABLE_SPECULATIVE_CCD on. Do not set directly! + + PxU8* frictionPtr; //!< InOut: Friction patch correlation data. Set each frame by solver. Can be retained for improved behaviour or discarded each frame. + PxU8 frictionCount; //!< The total number of friction patches in this pair + + PxReal* contactForces; //!< Out: A buffer for the solver to write applied contact forces to. + + PxU32 startFrictionPatchIndex; //!< Start index of friction patch in the correlation buffer. Set by friction correlation + PxU32 numFrictionPatches; //!< Total number of friction patches in this pair. Set by friction correlation + + PxU32 startContactPatchIndex; //!< The start index of this pair's contact patches in the correlation buffer. For internal use only + PxU16 numContactPatches; //!< Total number of contact patches. + PxU16 axisConstraintCount; //!< Axis constraint count. Defines how many constraint rows this pair has produced. Useful for statistical purposes. + + PxReal maxImpulse; + + PxReal torsionalPatchRadius; + PxReal minTorsionalPatchRadius; +}; + +#if !PX_DOXYGEN +} +#endif + +#if PX_VC +#pragma warning(pop) +#endif + +#endif + diff --git a/sources/PhysX/PhysX/include/task/PxCpuDispatcher.h b/sources/PhysX/PhysX/include/task/PxCpuDispatcher.h new file mode 100644 index 00000000..a9993d5c --- /dev/null +++ b/sources/PhysX/PhysX/include/task/PxCpuDispatcher.h @@ -0,0 +1,79 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. + +#ifndef PXTASK_PXCPUDISPATCHER_H +#define PXTASK_PXCPUDISPATCHER_H + +#include "task/PxTaskDefine.h" +#include "foundation/PxSimpleTypes.h" + +namespace physx +{ + +class PxBaseTask; + +/** + \brief A CpuDispatcher is responsible for scheduling the execution of tasks passed to it by the SDK. + + A typical implementation would for example use a thread pool with the dispatcher + pushing tasks onto worker thread queues or a global queue. + + @see PxBaseTask + @see PxTask + @see PxTaskManager +*/ +class PxCpuDispatcher +{ +public: + /** + \brief Called by the TaskManager when a task is to be queued for execution. + + Upon receiving a task, the dispatcher should schedule the task + to run when resource is available. After the task has been run, + it should call the release() method and discard it's pointer. + + \param[in] task The task to be run. + + @see PxBaseTask + */ + virtual void submitTask( PxBaseTask& task ) = 0; + + /** + \brief Returns the number of available worker threads for this dispatcher. + + The SDK will use this count to control how many tasks are submitted. By + matching the number of tasks with the number of execution units task + overhead can be reduced. + */ + virtual uint32_t getWorkerCount() const = 0; + + virtual ~PxCpuDispatcher() {} +}; + +} // end physx namespace + +#endif // PXTASK_PXCPUDISPATCHER_H diff --git a/sources/PhysX/PhysX/include/task/PxTask.h b/sources/PhysX/PhysX/include/task/PxTask.h new file mode 100644 index 00000000..d2040062 --- /dev/null +++ b/sources/PhysX/PhysX/include/task/PxTask.h @@ -0,0 +1,320 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. + +#ifndef PXTASK_PXTASK_H +#define PXTASK_PXTASK_H + +#include "task/PxTaskDefine.h" +#include "task/PxTaskManager.h" +#include "task/PxCpuDispatcher.h" +#include "foundation/PxAssert.h" + +namespace physx +{ + +/** + * \brief Base class of all task types + * + * PxBaseTask defines a runnable reference counted task with built-in profiling. + */ +class PxBaseTask +{ +public: + PxBaseTask() : mContextID(0), mTm(NULL) {} + virtual ~PxBaseTask() {} + + /** + * \brief The user-implemented run method where the task's work should be performed + * + * run() methods must be thread safe, stack friendly (no alloca, etc), and + * must never block. + */ + virtual void run() = 0; + + /** + * \brief Return a user-provided task name for profiling purposes. + * + * It does not have to be unique, but unique names are helpful. + * + * \return The name of this task + */ + virtual const char* getName() const = 0; + + //! \brief Implemented by derived implementation classes + virtual void addReference() = 0; + //! \brief Implemented by derived implementation classes + virtual void removeReference() = 0; + //! \brief Implemented by derived implementation classes + virtual int32_t getReference() const = 0; + + /** \brief Implemented by derived implementation classes + * + * A task may assume in its release() method that the task system no longer holds + * references to it - so it may safely run its destructor, recycle itself, etc. + * provided no additional user references to the task exist + */ + virtual void release() = 0; + + /** + * \brief Return PxTaskManager to which this task was submitted + * + * Note, can return NULL if task was not submitted, or has been + * completed. + */ + PX_FORCE_INLINE PxTaskManager* getTaskManager() const + { + return mTm; + } + + PX_FORCE_INLINE void setContextId(PxU64 id) { mContextID = id; } + PX_FORCE_INLINE PxU64 getContextId() const { return mContextID; } + +protected: + PxU64 mContextID; //!< Context ID for profiler interface + PxTaskManager* mTm; //!< Owning PxTaskManager instance + + friend class PxTaskMgr; +}; + + +/** + * \brief A PxBaseTask implementation with deferred execution and full dependencies + * + * A PxTask must be submitted to a PxTaskManager to to be executed, Tasks may + * optionally be named when they are submitted. + */ +class PxTask : public PxBaseTask +{ +public: + PxTask() : mTaskID(0) {} + virtual ~PxTask() {} + + //! \brief Release method implementation + virtual void release() + { + PX_ASSERT(mTm); + + // clear mTm before calling taskCompleted() for safety + PxTaskManager* save = mTm; + mTm = NULL; + save->taskCompleted( *this ); + } + + //! \brief Inform the PxTaskManager this task must finish before the given + // task is allowed to start. + PX_INLINE void finishBefore( PxTaskID taskID ) + { + PX_ASSERT(mTm); + mTm->finishBefore( *this, taskID); + } + + //! \brief Inform the PxTaskManager this task cannot start until the given + // task has completed. + PX_INLINE void startAfter( PxTaskID taskID ) + { + PX_ASSERT(mTm); + mTm->startAfter( *this, taskID ); + } + + /** + * \brief Manually increment this task's reference count. The task will + * not be allowed to run until removeReference() is called. + */ + PX_INLINE void addReference() + { + PX_ASSERT(mTm); + mTm->addReference( mTaskID ); + } + + /** + * \brief Manually decrement this task's reference count. If the reference + * count reaches zero, the task will be dispatched. + */ + PX_INLINE void removeReference() + { + PX_ASSERT(mTm); + mTm->decrReference( mTaskID ); + } + + /** + * \brief Return the ref-count for this task + */ + PX_INLINE int32_t getReference() const + { + return mTm->getReference( mTaskID ); + } + + /** + * \brief Return the unique ID for this task + */ + PX_INLINE PxTaskID getTaskID() const + { + return mTaskID; + } + + /** + * \brief Called by PxTaskManager at submission time for initialization + * + * Perform simulation step initialization here. + */ + virtual void submitted() + { + } + +protected: + PxTaskID mTaskID; //!< ID assigned at submission + + friend class PxTaskMgr; +}; + + +/** + * \brief A PxBaseTask implementation with immediate execution and simple dependencies + * + * A PxLightCpuTask bypasses the PxTaskManager launch dependencies and will be + * submitted directly to your scene's CpuDispatcher. When the run() function + * completes, it will decrement the reference count of the specified + * continuation task. + * + * You must use a full-blown PxTask if you want your task to be resolved + * by another PxTask, or you need more than a single dependency to be + * resolved when your task completes, or your task will not run on the + * CpuDispatcher. + */ +class PxLightCpuTask : public PxBaseTask +{ +public: + PxLightCpuTask() + : mCont( NULL ) + , mRefCount( 0 ) + { + } + virtual ~PxLightCpuTask() + { + mTm = NULL; + } + + /** + * \brief Initialize this task and specify the task that will have its ref count decremented on completion. + * + * Submission is deferred until the task's mRefCount is decremented to zero. + * Note that we only use the PxTaskManager to query the appropriate dispatcher. + * + * \param[in] tm The PxTaskManager this task is managed by + * \param[in] c The task to be executed when this task has finished running + */ + PX_INLINE void setContinuation(PxTaskManager& tm, PxBaseTask* c) + { + PX_ASSERT( mRefCount == 0 ); + mRefCount = 1; + mCont = c; + mTm = &tm; + if( mCont ) + { + mCont->addReference(); + } + } + + /** + * \brief Initialize this task and specify the task that will have its ref count decremented on completion. + * + * This overload of setContinuation() queries the PxTaskManager from the continuation + * task, which cannot be NULL. + * \param[in] c The task to be executed after this task has finished running + */ + PX_INLINE void setContinuation( PxBaseTask* c ) + { + PX_ASSERT( c ); + PX_ASSERT( mRefCount == 0 ); + mRefCount = 1; + mCont = c; + if( mCont ) + { + mCont->addReference(); + mTm = mCont->getTaskManager(); + PX_ASSERT( mTm ); + } + } + + /** + * \brief Retrieves continuation task + */ + PX_INLINE PxBaseTask* getContinuation() const + { + return mCont; + } + + /** + * \brief Manually decrement this task's reference count. If the reference + * count reaches zero, the task will be dispatched. + */ + PX_INLINE void removeReference() + { + mTm->decrReference(*this); + } + + /** \brief Return the ref-count for this task */ + PX_INLINE int32_t getReference() const + { + return mRefCount; + } + + /** + * \brief Manually increment this task's reference count. The task will + * not be allowed to run until removeReference() is called. + */ + PX_INLINE void addReference() + { + mTm->addReference(*this); + } + + /** + * \brief called by CpuDispatcher after run method has completed + * + * Decrements the continuation task's reference count, if specified. + */ + PX_INLINE void release() + { + if( mCont ) + { + mCont->removeReference(); + } + } + +protected: + + PxBaseTask* mCont; //!< Continuation task, can be NULL + volatile int32_t mRefCount; //!< PxTask is dispatched when reaches 0 + + friend class PxTaskMgr; +}; + + +}// end physx namespace + + +#endif // PXTASK_PXTASK_H diff --git a/sources/PhysX/PhysX/include/task/PxTaskDefine.h b/sources/PhysX/PhysX/include/task/PxTaskDefine.h new file mode 100644 index 00000000..401d36eb --- /dev/null +++ b/sources/PhysX/PhysX/include/task/PxTaskDefine.h @@ -0,0 +1,37 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. + +#ifndef PXTASK_PXTASKDEFINE_H +#define PXTASK_PXTASKDEFINE_H + +#include "foundation/PxPreprocessor.h" + +#ifndef PX_SUPPORT_PXTASK_PROFILING +#define PX_SUPPORT_PXTASK_PROFILING 1 +#endif + +#endif // PXTASK_PXTASKDEFINE_H diff --git a/sources/PhysX/PhysX/include/task/PxTaskManager.h b/sources/PhysX/PhysX/include/task/PxTaskManager.h new file mode 100644 index 00000000..003bbb6c --- /dev/null +++ b/sources/PhysX/PhysX/include/task/PxTaskManager.h @@ -0,0 +1,204 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. + +#ifndef PXTASK_PXTASKMANAGER_H +#define PXTASK_PXTASKMANAGER_H + +#include "task/PxTaskDefine.h" +#include "foundation/PxSimpleTypes.h" +#include "foundation/PxErrorCallback.h" + +namespace physx +{ +PX_PUSH_PACK_DEFAULT + +class PxBaseTask; +class PxTask; +class PxLightCpuTask; +typedef unsigned int PxTaskID; + +/** +\brief Identifies the type of each heavyweight PxTask object + +\note This enum type is only used by PxTask and GpuTask objects, LightCpuTasks do not use this enum. + +@see PxTask +@see PxLightCpuTask +*/ +struct PxTaskType +{ + /** + * \brief Identifies the type of each heavyweight PxTask object + */ + enum Enum + { + TT_CPU, //!< PxTask will be run on the CPU + TT_NOT_PRESENT, //!< Return code when attempting to find a task that does not exist + TT_COMPLETED //!< PxTask execution has been completed + }; +}; + +class PxCpuDispatcher; + +/** + \brief The PxTaskManager interface + + A PxTaskManager instance holds references to user-provided dispatcher objects, when tasks are + submitted the PxTaskManager routes them to the appropriate dispatcher and handles task profiling if enabled. + Users should not implement the PxTaskManager interface, the SDK creates its own concrete PxTaskManager object + per-scene which users can configure by passing dispatcher objects into the PxSceneDesc. + + @see CpuDispatcher + +*/ +class PxTaskManager +{ +public: + + /** + \brief Set the user-provided dispatcher object for CPU tasks + + \param[in] ref The dispatcher object. + + @see CpuDispatcher + */ + virtual void setCpuDispatcher(PxCpuDispatcher& ref) = 0; + + /** + \brief Get the user-provided dispatcher object for CPU tasks + + \return The CPU dispatcher object. + + @see CpuDispatcher + */ + virtual PxCpuDispatcher* getCpuDispatcher() const = 0; + + /** + \brief Reset any dependencies between Tasks + + \note Will be called at the start of every frame before tasks are submitted. + + @see PxTask + */ + virtual void resetDependencies() = 0; + + /** + \brief Called by the owning scene to start the task graph. + + \note All tasks with with ref count of 1 will be dispatched. + + @see PxTask + */ + virtual void startSimulation() = 0; + + /** + \brief Called by the owning scene at the end of a simulation step. + */ + virtual void stopSimulation() = 0; + + /** + \brief Called by the worker threads to inform the PxTaskManager that a task has completed processing + + \param[in] task The task which has been completed + */ + virtual void taskCompleted(PxTask& task) = 0; + + /** + \brief Retrieve a task by name + + \param[in] name The unique name of a task + \return The ID of the task with that name, or TT_NOT_PRESENT if not found + */ + virtual PxTaskID getNamedTask(const char* name) = 0; + + /** + \brief Submit a task with a unique name. + + \param[in] task The task to be executed + \param[in] name The unique name of a task + \param[in] type The type of the task (default TT_CPU) + \return The ID of the task with that name, or TT_NOT_PRESENT if not found + */ + virtual PxTaskID submitNamedTask(PxTask* task, const char* name, PxTaskType::Enum type = PxTaskType::TT_CPU) = 0; + + /** + \brief Submit an unnamed task. + + \param[in] task The task to be executed + \param[in] type The type of the task (default TT_CPU) + + \return The ID of the task with that name, or TT_NOT_PRESENT if not found + */ + virtual PxTaskID submitUnnamedTask(PxTask& task, PxTaskType::Enum type = PxTaskType::TT_CPU) = 0; + + /** + \brief Retrieve a task given a task ID + + \param[in] id The ID of the task to return, a valid ID must be passed or results are undefined + + \return The task associated with the ID + */ + virtual PxTask* getTaskFromID(PxTaskID id) = 0; + + /** + \brief Release the PxTaskManager object, referenced dispatchers will not be released + */ + virtual void release() = 0; + + /** + \brief Construct a new PxTaskManager instance with the given [optional] dispatchers + */ + static PxTaskManager* createTaskManager(PxErrorCallback& errorCallback, PxCpuDispatcher* = 0); + +protected: + virtual ~PxTaskManager() {} + + /*! \cond PRIVATE */ + + virtual void finishBefore(PxTask& task, PxTaskID taskID) = 0; + virtual void startAfter(PxTask& task, PxTaskID taskID) = 0; + + virtual void addReference(PxTaskID taskID) = 0; + virtual void decrReference(PxTaskID taskID) = 0; + virtual int32_t getReference(PxTaskID taskID) const = 0; + + virtual void decrReference(PxLightCpuTask&) = 0; + virtual void addReference(PxLightCpuTask&) = 0; + + /*! \endcond */ + + friend class PxBaseTask; + friend class PxTask; + friend class PxLightCpuTask; +}; + +PX_POP_PACK + +} // end physx namespace + + +#endif // PXTASK_PXTASKMANAGER_H diff --git a/sources/PhysX/PhysX/include/vehicle/PxVehicleComponents.h b/sources/PhysX/PhysX/include/vehicle/PxVehicleComponents.h new file mode 100644 index 00000000..dbf0a1c6 --- /dev/null +++ b/sources/PhysX/PhysX/include/vehicle/PxVehicleComponents.h @@ -0,0 +1,1359 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_VEHICLE_CORE_COMPONENTS_H +#define PX_VEHICLE_CORE_COMPONENTS_H +/** \addtogroup vehicle + @{ +*/ + +#include "foundation/PxMemory.h" +#include "foundation/PxVec3.h" +#include "common/PxCoreUtilityTypes.h" +#include "vehicle/PxVehicleSDK.h" +#include "common/PxTypeInfo.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxVehicleChassisData +{ +public: + + friend class PxVehicleDriveSimData4W; + + PxVehicleChassisData() + : mMOI(PxVec3(0,0,0)), + mMass(1500), + mCMOffset(PxVec3(0,0,0)) + { + } + + /** + \brief Moment of inertia of vehicle rigid body actor. + + \note Specified in kilograms metres-squared (kg m^2). + */ + PxVec3 mMOI; + + /** + \brief Mass of vehicle rigid body actor. + + \note Specified in kilograms (kg). + */ + PxReal mMass; + + /** + \brief Center of mass offset of vehicle rigid body actor. + + \note Specified in metres (m). + */ + PxVec3 mCMOffset; + +private: + + PxReal pad; + + bool isValid() const; +}; +PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleChassisData)& 0x0f)); + +class PxVehicleEngineData +{ +public: + + friend class PxVehicleDriveSimData; + + enum + { + eMAX_NB_ENGINE_TORQUE_CURVE_ENTRIES = 8 + }; + + PxVehicleEngineData() + : mMOI(1.0f), + mPeakTorque(500.0f), + mMaxOmega(600.0f), + mDampingRateFullThrottle(0.15f), + mDampingRateZeroThrottleClutchEngaged(2.0f), + mDampingRateZeroThrottleClutchDisengaged(0.35f) + { + mTorqueCurve.addPair(0.0f, 0.8f); + mTorqueCurve.addPair(0.33f, 1.0f); + mTorqueCurve.addPair(1.0f, 0.8f); + + mRecipMOI=1.0f/mMOI; + mRecipMaxOmega=1.0f/mMaxOmega; + } + + /** + \brief Graph of normalized torque (torque/mPeakTorque) against normalized engine speed ( engineRotationSpeed / mMaxOmega ). + + \note The normalized engine speed is the x-axis of the graph, while the normalized torque is the y-axis of the graph. + */ + PxFixedSizeLookupTable mTorqueCurve; + + /** + \brief Moment of inertia of the engine around the axis of rotation. + + \note Specified in kilograms metres-squared (kg m^2) + */ + PxReal mMOI; + + /** + \brief Maximum torque available to apply to the engine when the accelerator pedal is at maximum. + + \note The torque available is the value of the accelerator pedal (in range [0, 1]) multiplied by the normalized torque as computed from mTorqueCurve multiplied by mPeakTorque. + + \note Specified in kilograms metres-squared per second-squared (kg m^2 s^-2). + + Range: [0, PX_MAX_F32)
+ */ + PxReal mPeakTorque; + + /** + \brief Maximum rotation speed of the engine. + + \note Specified in radians per second (s^-1). + + Range: [0, PX_MAX_F32)
+ */ + PxReal mMaxOmega; + + /** + \brief Damping rate of engine when full throttle is applied. + + \note If the clutch is engaged (any gear except neutral) then the damping rate applied at run-time is an interpolation + between mDampingRateZeroThrottleClutchEngaged and mDampingRateFullThrottle: + mDampingRateZeroThrottleClutchEngaged + (mDampingRateFullThrottle-mDampingRateZeroThrottleClutchEngaged)*acceleratorPedal; + + \note If the clutch is disengaged (in neutral gear) the damping rate applied at run-time is an interpolation + between mDampingRateZeroThrottleClutchDisengaged and mDampingRateFullThrottle: + mDampingRateZeroThrottleClutchDisengaged + (mDampingRateFullThrottle-mDampingRateZeroThrottleClutchDisengaged)*acceleratorPedal; + + \note Specified in kilograms metres-squared per second (kg m^2 s^-1). + + Range: [0, PX_MAX_F32)
+ */ + PxReal mDampingRateFullThrottle; + + + /** + \brief Damping rate of engine when full throttle is applied. + + \note If the clutch is engaged (any gear except neutral) then the damping rate applied at run-time is an interpolation + between mDampingRateZeroThrottleClutchEngaged and mDampingRateFullThrottle: + mDampingRateZeroThrottleClutchEngaged + (mDampingRateFullThrottle-mDampingRateZeroThrottleClutchEngaged)*acceleratorPedal; + + \note If the clutch is disengaged (in neutral gear) the damping rate applied at run-time is an interpolation + between mDampingRateZeroThrottleClutchDisengaged and mDampingRateFullThrottle: + mDampingRateZeroThrottleClutchDisengaged + (mDampingRateFullThrottle-mDampingRateZeroThrottleClutchDisengaged)*acceleratorPedal; + + \note Specified in kilograms metres-squared per second (kg m^2 s^-1). + + Range: [0, PX_MAX_F32)
+ */ + PxReal mDampingRateZeroThrottleClutchEngaged; + + /** + \brief Damping rate of engine when full throttle is applied. + + \note If the clutch is engaged (any gear except neutral) then the damping rate applied at run-time is an interpolation + between mDampingRateZeroThrottleClutchEngaged and mDampingRateFullThrottle: + mDampingRateZeroThrottleClutchEngaged + (mDampingRateFullThrottle-mDampingRateZeroThrottleClutchEngaged)*acceleratorPedal; + + \note If the clutch is disengaged (in neutral gear) the damping rate applied at run-time is an interpolation + between mDampingRateZeroThrottleClutchDisengaged and mDampingRateFullThrottle: + mDampingRateZeroThrottleClutchDisengaged + (mDampingRateFullThrottle-mDampingRateZeroThrottleClutchDisengaged)*acceleratorPedal; + + \note Specified in kilograms metres-squared per second (kg m^2 s^-1). + + Range: [0, PX_MAX_F32)
+ */ + PxReal mDampingRateZeroThrottleClutchDisengaged; + + /** + \brief Return value of mRecipMOI(=1.0f/mMOI) that is automatically set by PxVehicleDriveSimData::setEngineData + */ + PX_FORCE_INLINE PxReal getRecipMOI() const {return mRecipMOI;} + + /** + \brief Return value of mRecipMaxOmega( = 1.0f / mMaxOmega ) that is automatically set by PxVehicleDriveSimData::setEngineData + */ + PX_FORCE_INLINE PxReal getRecipMaxOmega() const {return mRecipMaxOmega;} + +private: + + /** + \brief Reciprocal of the engine moment of inertia. + + \note Not necessary to set this value because it is set by PxVehicleDriveSimData::setEngineData + + Range: [0, PX_MAX_F32)
+ */ + PxReal mRecipMOI; + + /** + \brief Reciprocal of the maximum rotation speed of the engine. + + \note Not necessary to set this value because it is set by PxVehicleDriveSimData::setEngineData + + Range: [0, PX_MAX_F32)
+ */ + PxReal mRecipMaxOmega; + + bool isValid() const; + + +//serialization +public: + PxVehicleEngineData(const PxEMPTY) : mTorqueCurve(PxEmpty) {} +//~serialization +}; +PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleEngineData)& 0x0f)); + +class PxVehicleGearsData +{ +public: + + friend class PxVehicleDriveSimData; + + enum Enum + { + eREVERSE=0, + eNEUTRAL, + eFIRST, + eSECOND, + eTHIRD, + eFOURTH, + eFIFTH, + eSIXTH, + eSEVENTH, + eEIGHTH, + eNINTH, + eTENTH, + eELEVENTH, + eTWELFTH, + eTHIRTEENTH, + eFOURTEENTH, + eFIFTEENTH, + eSIXTEENTH, + eSEVENTEENTH, + eEIGHTEENTH, + eNINETEENTH, + eTWENTIETH, + eTWENTYFIRST, + eTWENTYSECOND, + eTWENTYTHIRD, + eTWENTYFOURTH, + eTWENTYFIFTH, + eTWENTYSIXTH, + eTWENTYSEVENTH, + eTWENTYEIGHTH, + eTWENTYNINTH, + eTHIRTIETH, + eGEARSRATIO_COUNT + }; + + PxVehicleGearsData() + : mFinalRatio(4.0f), + mNbRatios(7), + mSwitchTime(0.5f) + { + mRatios[PxVehicleGearsData::eREVERSE]=-4.0f; + mRatios[PxVehicleGearsData::eNEUTRAL]=0.0f; + mRatios[PxVehicleGearsData::eFIRST]=4.0f; + mRatios[PxVehicleGearsData::eSECOND]=2.0f; + mRatios[PxVehicleGearsData::eTHIRD]=1.5f; + mRatios[PxVehicleGearsData::eFOURTH]=1.1f; + mRatios[PxVehicleGearsData::eFIFTH]=1.0f; + + for(PxU32 i = PxVehicleGearsData::eSIXTH; i < PxVehicleGearsData::eGEARSRATIO_COUNT; ++i) + mRatios[i]=0.f; + } + + /** + \brief Gear ratios + + Range: [0, PX_MAX_F32)
+ */ + PxReal mRatios[PxVehicleGearsData::eGEARSRATIO_COUNT]; + + /** + \brief Gear ratio applied is mRatios[currentGear]*finalRatio + + Range: [0, PX_MAX_F32)
+ */ + PxReal mFinalRatio; + + /** + \brief Number of gears (including reverse and neutral). + + Range: (0, MAX_NB_GEAR_RATIOS)
+ */ + PxU32 mNbRatios; + + /** + \brief Time it takes to switch gear. + + \note Specified in seconds (s). + + Range: [0, PX_MAX_F32)
+ */ + PxReal mSwitchTime; + +private: + + PxReal mPad; + + bool isValid() const; + +//serialization +public: + PxVehicleGearsData(const PxEMPTY) {} + PxReal getGearRatio(PxVehicleGearsData::Enum a) const {return mRatios[a];} + void setGearRatio(PxVehicleGearsData::Enum a, PxReal ratio) { mRatios[a] = ratio;} +//~serialization +}; +PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleGearsData)& 0x0f)); + +class PxVehicleAutoBoxData +{ +public: + + friend class PxVehicleDriveSimData; + + PxVehicleAutoBoxData() + { + for(PxU32 i=0;i mUpRatios[currentGear] the autobox will begin + a transition to currentGear+1 unless currentGear is the highest possible gear or neutral or reverse. + + Range: [0, 1]
+ */ + PxReal mUpRatios[PxVehicleGearsData::eGEARSRATIO_COUNT]; + + /** + \brief Value of engineRevs/maxEngineRevs that is low enough to decrement gear. + + \note When ( engineRotationSpeed / PxVehicleEngineData::mMaxOmega ) < mDownRatios[currentGear] the autobox will begin + a transition to currentGear-1 unless currentGear is first gear or neutral or reverse. + + Range: [0, 1]
+ */ + PxReal mDownRatios[PxVehicleGearsData::eGEARSRATIO_COUNT]; + + /** + \brief Set the latency time of the autobox. + + \note Latency time is the minimum time that must pass between each gear change that is initiated by the autobox. + The auto-box will only attempt to initiate another gear change up or down if the simulation time that has passed since the most recent + automated gear change is greater than the specified latency. + + \note Specified in seconds (s). + + @see getLatency + */ + void setLatency(const PxReal latency) + { + mDownRatios[PxVehicleGearsData::eREVERSE]=latency; + } + + /** + \brief Get the latency time of the autobox. + + \note Specified in seconds (s). + + @see setLatency + */ + PxReal getLatency() const + { + return mDownRatios[PxVehicleGearsData::eREVERSE]; + } + +private: + bool isValid() const; + +//serialization +public: + PxVehicleAutoBoxData(const PxEMPTY) {} + + PxReal getUpRatios(PxVehicleGearsData::Enum a) const {return mUpRatios[a];} + void setUpRatios(PxVehicleGearsData::Enum a, PxReal ratio) { mUpRatios[a] = ratio;} + + PxReal getDownRatios(PxVehicleGearsData::Enum a) const {return mDownRatios[a];} + void setDownRatios(PxVehicleGearsData::Enum a, PxReal ratio) { mDownRatios[a] = ratio;} +//~serialization +}; +PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleAutoBoxData)& 0x0f)); + +class PxVehicleDifferential4WData +{ +public: + + friend class PxVehicleDriveSimData4W; + + enum Enum + { + eDIFF_TYPE_LS_4WD, //limited slip differential for car with 4 driven wheels + eDIFF_TYPE_LS_FRONTWD, //limited slip differential for car with front-wheel drive + eDIFF_TYPE_LS_REARWD, //limited slip differential for car with rear-wheel drive + eDIFF_TYPE_OPEN_4WD, //open differential for car with 4 driven wheels + eDIFF_TYPE_OPEN_FRONTWD, //open differential for car with front-wheel drive + eDIFF_TYPE_OPEN_REARWD, //open differential for car with rear-wheel drive + eMAX_NB_DIFF_TYPES + }; + + PxVehicleDifferential4WData() + : mFrontRearSplit(0.45f), + mFrontLeftRightSplit(0.5f), + mRearLeftRightSplit(0.5f), + mCentreBias(1.3f), + mFrontBias(1.3f), + mRearBias(1.3f), + mType(PxVehicleDifferential4WData::eDIFF_TYPE_LS_4WD) + { + } + + /** + \brief Ratio of torque split between front and rear (>0.5 means more to front, <0.5 means more to rear). + + \note Only applied to DIFF_TYPE_LS_4WD and eDIFF_TYPE_OPEN_4WD + + Range: [0, 1]
+ */ + PxReal mFrontRearSplit; + + /** + \brief Ratio of torque split between front-left and front-right (>0.5 means more to front-left, <0.5 means more to front-right). + + \note Only applied to DIFF_TYPE_LS_4WD and eDIFF_TYPE_OPEN_4WD and eDIFF_TYPE_LS_FRONTWD + + Range: [0, 1]
+ */ + PxReal mFrontLeftRightSplit; + + /** + \brief Ratio of torque split between rear-left and rear-right (>0.5 means more to rear-left, <0.5 means more to rear-right). + + \note Only applied to DIFF_TYPE_LS_4WD and eDIFF_TYPE_OPEN_4WD and eDIFF_TYPE_LS_REARWD + + Range: [0, 1]
+ */ + PxReal mRearLeftRightSplit; + + /** + \brief Maximum allowed ratio of average front wheel rotation speed and rear wheel rotation speeds + The differential will divert more torque to the slower wheels when the bias is exceeded. + + \note Only applied to DIFF_TYPE_LS_4WD + + Range: [1, PX_MAX_F32)
+ */ + PxReal mCentreBias; + + /** + \brief Maximum allowed ratio of front-left and front-right wheel rotation speeds. + The differential will divert more torque to the slower wheel when the bias is exceeded. + + \note Only applied to DIFF_TYPE_LS_4WD and DIFF_TYPE_LS_FRONTWD + + Range: [1, PX_MAX_F32)
+ */ + PxReal mFrontBias; + + /** + \brief Maximum allowed ratio of rear-left and rear-right wheel rotation speeds. + The differential will divert more torque to the slower wheel when the bias is exceeded. + + \note Only applied to DIFF_TYPE_LS_4WD and DIFF_TYPE_LS_REARWD + + Range: [1, PX_MAX_F32)
+ */ + PxReal mRearBias; + + /** + \brief Type of differential. + + Range: [DIFF_TYPE_LS_4WD, DIFF_TYPE_OPEN_FRONTWD]
+ */ + PxVehicleDifferential4WData::Enum mType; + +private: + + PxReal mPad[1]; + + bool isValid() const; + +//serialization +public: + PxVehicleDifferential4WData(const PxEMPTY) {} +//~serialization +}; +PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleDifferential4WData)& 0x0f)); + +class PxVehicleDifferentialNWData +{ +public: + + friend class PxVehicleDriveSimDataNW; + friend class PxVehicleUpdate; + + PxVehicleDifferentialNWData() + { + PxMemSet(mBitmapBuffer, 0, sizeof(PxU32) * (((PX_MAX_NB_WHEELS + 31) & ~31) >> 5)); + mNbDrivenWheels=0; + mInvNbDrivenWheels=0.0f; + } + + /** + \brief Set a specific wheel to be driven or non-driven by the differential. + + \note The available drive torque will be split equally between all driven wheels. + Zero torque will be applied to non-driven wheels. + The default state of each wheel is to be uncoupled to the differential. + */ + void setDrivenWheel(const PxU32 wheelId, const bool drivenState); + + /** + \brief Test if a specific wheel has been configured as a driven or non-driven wheel. + */ + bool getIsDrivenWheel(const PxU32 wheelId) const; + +private: + + PxU32 mBitmapBuffer[((PX_MAX_NB_WHEELS + 31) & ~31) >> 5]; + PxU32 mNbDrivenWheels; + PxReal mInvNbDrivenWheels; + PxU32 mPad; + + bool isValid() const; + +//serialization +public: + PxVehicleDifferentialNWData(const PxEMPTY) {} + PxU32 getDrivenWheelStatus() const; + void setDrivenWheelStatus(PxU32 status); +//~serialization +}; +PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleDifferentialNWData)& 0x0f)); + + +class PxVehicleAckermannGeometryData +{ +public: + + friend class PxVehicleDriveSimData4W; + + PxVehicleAckermannGeometryData() + : mAccuracy(1.0f), + mFrontWidth(0.0f), //Must be filled out + mRearWidth(0.0f), //Must be filled out + mAxleSeparation(0.0f) //Must be filled out + { + } + + /** + \brief Accuracy of Ackermann steer calculation. + + \note Accuracy with value 0.0 results in no Ackermann steer-correction, while + accuracy with value 1.0 results in perfect Ackermann steer-correction. + + \note Perfect Ackermann steer correction modifies the steer angles applied to the front-left and + front-right wheels so that the perpendiculars to the wheels' longitudinal directions cross the + extended vector of the rear axle at the same point. It is also applied to any steer angle applied + to the rear wheels but instead using the extended vector of the front axle. + + \note In general, more steer correction produces better cornering behavior. + + Range: [0, 1]
+ */ + PxReal mAccuracy; + + /** + \brief Distance between center-point of the two front wheels. + + \note Specified in metres (m). + + Range: [0, PX_MAX_F32)
+ */ + PxReal mFrontWidth; + + /** + \brief Distance between center-point of the two rear wheels. + + \note Specified in metres (m). + + Range: [0, PX_MAX_F32)
+ */ + PxReal mRearWidth; + + /** + \brief Distance between center of front axle and center of rear axle. + + \note Specified in metres (m). + + Range: [0, PX_MAX_F32)
+ */ + PxReal mAxleSeparation; + +private: + + bool isValid() const; + +//serialization +public: + PxVehicleAckermannGeometryData(const PxEMPTY) {} +//~serialization +}; +PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleAckermannGeometryData)& 0x0f)); + +/** +\brief Choose between a potentially more expensive but more accurate solution to the clutch model or a potentially cheaper but less accurate solution. +@see PxVehicleClutchData +*/ +struct PxVehicleClutchAccuracyMode +{ + enum Enum + { + eESTIMATE = 0, + eBEST_POSSIBLE + }; +}; + +class PxVehicleClutchData +{ +public: + + friend class PxVehicleDriveSimData; + + PxVehicleClutchData() + : mStrength(10.0f), + mAccuracyMode(PxVehicleClutchAccuracyMode::eBEST_POSSIBLE), + mEstimateIterations(5) + { + } + + /** + \brief Strength of clutch. + + \note The clutch is the mechanism that couples the engine to the wheels. + A stronger clutch more strongly couples the engine to the wheels, while a + clutch of strength zero completely decouples the engine from the wheels. + Stronger clutches more quickly bring the wheels and engine into equilibrium, while weaker + clutches take longer, resulting in periods of clutch slip and delays in power transmission + from the engine to the wheels. + The torque generated by the clutch is proportional to the clutch strength and + the velocity difference between the engine's rotational speed and the rotational speed of the + driven wheels after accounting for the gear ratio. + The torque at the clutch is applied negatively to the engine and positively to the driven wheels. + + \note Specified in kilograms metres-squared per second (kg m^2 s^-1) + + Range: [0,PX_MAX_F32)
+ */ + PxReal mStrength; + + /** + \brief The engine and wheel rotation speeds that are coupled through the clutch can be updated by choosing + one of two modes: eESTIMATE and eBEST_POSSIBLE. + + \note If eESTIMATE is chosen the vehicle sdk will update the wheel and engine rotation speeds + with estimated values to the implemented clutch model. + + \note If eBEST_POSSIBLE is chosen the vehicle sdk will compute the best possible + solution (within floating point tolerance) to the implemented clutch model. + This is the recommended mode. + + \note The clutch model remains the same if either eESTIMATE or eBEST_POSSIBLE is chosen but the accuracy and + computational cost of the solution to the model can be tuned as required. + */ + PxVehicleClutchAccuracyMode::Enum mAccuracyMode; + + /** + \brief Tune the mathematical accuracy and computational cost of the computed estimate to the wheel and + engine rotation speeds if eESTIMATE is chosen. + + \note As mEstimateIterations increases the computational cost of the clutch also increases and the solution + approaches the solution that would be computed if eBEST_POSSIBLE was chosen instead. + + \note This has no effect if eBEST_POSSIBLE is chosen as the accuracy mode. + + \note A value of zero is not allowed if eESTIMATE is chosen as the accuracy mode. + */ + PxU32 mEstimateIterations; + +private: + + PxU8 mPad[4]; + + bool isValid() const; + +//serialization +public: + PxVehicleClutchData(const PxEMPTY) {} +//~serialization +}; +PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleClutchData)& 0x0f)); + + +/** +\brief Tire load variation can be strongly dependent on the time-step so it is a good idea to filter it +to give less jerky handling behavior. + +\note The x-axis of the graph is normalized tire load, while the y-axis is the filtered normalized tire load. + +\note The normalized load is the force acting downwards on the tire divided by the force experienced by the tire when the car is at rest on the ground. + +\note The rest load is approximately the product of the value of gravitational acceleration and PxVehicleSuspensionData::mSprungMass. + +\note The minimum possible normalized load is zero. + +\note There are two points on the graph: (mMinNormalisedLoad, mMinNormalisedFilteredLoad) and (mMaxNormalisedLoad, mMaxFilteredNormalisedLoad). + +\note Normalized loads less than mMinNormalisedLoad have filtered normalized load = mMinNormalisedFilteredLoad. + +\note Normalized loads greater than mMaxNormalisedLoad have filtered normalized load = mMaxFilteredNormalisedLoad. + +\note Normalized loads in-between are linearly interpolated between mMinNormalisedFilteredLoad and mMaxFilteredNormalisedLoad. + +\note The tire load applied as input to the tire force computation is the filtered normalized load multiplied by the rest load. +*/ +class PxVehicleTireLoadFilterData +{ +public: + + friend class PxVehicleWheelsSimData; + + PxVehicleTireLoadFilterData() + : mMinNormalisedLoad(0), + mMinFilteredNormalisedLoad(0.2308f), + mMaxNormalisedLoad(3.0f), + mMaxFilteredNormalisedLoad(3.0f) + { + mDenominator=1.0f/(mMaxNormalisedLoad - mMinNormalisedLoad); + } + + /** + \brief Graph point (mMinNormalisedLoad,mMinFilteredNormalisedLoad) + */ + PxReal mMinNormalisedLoad; + + /** + \brief Graph point (mMinNormalisedLoad,mMinFilteredNormalisedLoad) + */ + PxReal mMinFilteredNormalisedLoad; + + /** + \brief Graph point (mMaxNormalisedLoad,mMaxFilteredNormalisedLoad) + */ + PxReal mMaxNormalisedLoad; + + /** + \brief Graph point (mMaxNormalisedLoad,mMaxFilteredNormalisedLoad) + */ + PxReal mMaxFilteredNormalisedLoad; + + PX_FORCE_INLINE PxReal getDenominator() const {return mDenominator;} + +private: + + /** + \brief Not necessary to set this value. + */ + //1.0f/(mMaxNormalisedLoad-mMinNormalisedLoad) for quick calculations + PxReal mDenominator; + + PxU32 mPad[3]; + + bool isValid() const; + +//serialization +public: + PxVehicleTireLoadFilterData(const PxEMPTY) {} +//~serialization +}; +PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleTireLoadFilterData)& 0x0f)); + +class PxVehicleWheelData +{ +public: + + friend class PxVehicleWheels4SimData; + + PxVehicleWheelData() + : mRadius(0.0f), //Must be filled out + mWidth(0.0f), + mMass(20.0f), + mMOI(0.0f), //Must be filled out + mDampingRate(0.25f), + mMaxBrakeTorque(1500.0f), + mMaxHandBrakeTorque(0.0f), + mMaxSteer(0.0f), + mToeAngle(0.0f), + mRecipRadius(0.0f), //Must be filled out + mRecipMOI(0.0f) //Must be filled out + { + } + + /** + \brief Radius of unit that includes metal wheel plus rubber tire. + + \note Specified in metres (m). + + Range: [0, PX_MAX_F32)
+ */ + PxReal mRadius; + + /** + \brief Maximum width of unit that includes wheel plus tire. + + \note Specified in metres (m). + + Range: [0, PX_MAX_F32)
+ */ + PxReal mWidth; + + /** + \brief Mass of unit that includes wheel plus tire. + + \note Specified in kilograms (kg). + + Range: [0, PX_MAX_F32)
+ */ + PxReal mMass; + + /** + \brief Moment of inertia of unit that includes wheel plus tire about the rolling axis. + + \note Specified in kilograms metres-squared (kg m^2). + + Range: [0, PX_MAX_F32)
+ */ + PxReal mMOI; + + /** + \brief Damping rate applied to wheel. + + \note Specified in kilograms metres-squared per second (kg m^2 s^-1). + + Range: [0, PX_MAX_F32)
+ */ + PxReal mDampingRate; + + /** + \brief Max brake torque that can be applied to wheel. + + \note Specified in kilograms metres-squared per second-squared (kg m^2 s^-2) + + Range: [0, PX_MAX_F32)
+ */ + PxReal mMaxBrakeTorque; + + /** + \brief Max handbrake torque that can be applied to wheel. + + \note Specified in kilograms metres-squared per second-squared (kg m^2 s^-2) + + Range: [0, PX_MAX_F32)
+ */ + PxReal mMaxHandBrakeTorque; + + /** + \brief Max steer angle that can be achieved by the wheel. + + \note Specified in radians. + + Range: [0, PX_MAX_F32)
+ */ + PxReal mMaxSteer; + + /** + \brief Wheel toe angle. This value is ignored by PxVehicleDriveTank and PxVehicleNoDrive. + + \note Specified in radians. + + Range: [0, Pi/2]
+ */ + PxReal mToeAngle;//in radians + + /** + \brief Return value equal to 1.0f/mRadius + + @see PxVehicleWheelsSimData::setWheelData + */ + PX_FORCE_INLINE PxReal getRecipRadius() const {return mRecipRadius;} + + /** + \brief Return value equal to 1.0f/mRecipMOI + + @see PxVehicleWheelsSimData::setWheelData + */ + PX_FORCE_INLINE PxReal getRecipMOI() const {return mRecipMOI;} + +private: + + /** + \brief Reciprocal of radius of unit that includes metal wheel plus rubber tire. + + \note Not necessary to set this value because it is set by PxVehicleWheelsSimData::setWheelData + + Range: [0, PX_MAX_F32)
+ */ + PxReal mRecipRadius; + + /** + \brief Reciprocal of moment of inertia of unit that includes wheel plus tire about single allowed axis of rotation. + + \note Not necessary to set this value because it is set by PxVehicleWheelsSimData::setWheelData + + Range: [0, PX_MAX_F32)
+ */ + PxReal mRecipMOI; + + PxReal mPad[1]; + + bool isValid() const; +}; +PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleWheelData)& 0x0f)); + +class PxVehicleSuspensionData +{ +public: + + friend class PxVehicleWheels4SimData; + + PxVehicleSuspensionData() + : mSpringStrength(0.0f), + mSpringDamperRate(0.0f), + mMaxCompression(0.3f), + mMaxDroop(0.1f), + mSprungMass(0.0f), + mCamberAtRest(0.0f), + mCamberAtMaxCompression(0.0f), + mCamberAtMaxDroop(0.0f), + mRecipMaxCompression(1.0f), + mRecipMaxDroop(1.0f) + { + } + + /** + \brief Spring strength of suspension unit. + + \note Specified in kilograms per second-squared (kg s^-2). + + Range: [0, PX_MAX_F32)
+ */ + PxReal mSpringStrength; + + /** + \brief Spring damper rate of suspension unit. + + \note Specified in kilograms per second (kg s^-1). + + Range: [0, PX_MAX_F32)
+ */ + PxReal mSpringDamperRate; + + /** + \brief Maximum compression allowed by suspension spring. + + \note Specified in metres (m). + + Range: [0, PX_MAX_F32)
+ */ + PxReal mMaxCompression; + + /** + \brief Maximum elongation allowed by suspension spring. + + \note Specified in metres (m). + + Range: [0, PX_MAX_F32)
+ */ + PxReal mMaxDroop; + + /** + \brief Mass of vehicle that is supported by suspension spring. + + \note Specified in kilograms (kg). + + \note Each suspension is guaranteed to generate an upwards force of |gravity|*mSprungMass along the suspension direction when the wheel is perfectly + at rest and sitting at the rest pose defined by the wheel centre offset. + + \note The sum of the sprung masses of all suspensions of a vehicle should match the mass of the PxRigidDynamic associated with the vehicle. + When this condition is satisfied for a vehicle on a horizontal plane the wheels of the vehicle are guaranteed to sit at the rest pose + defined by the wheel centre offset. The mass matching condition is not enforced. + + \note As the wheel compresses or elongates along the suspension direction the force generated by the spring is + F = |gravity|*mSprungMass + deltaX*mSpringStrength + deltaXDot*mSpringDamperRate + where deltaX is the deviation from the defined rest pose and deltaXDot is the velocity of the sprung mass along the suspension direction. + In practice, deltaXDot is computed by comparing the current and previous deviation from the rest pose and dividing the difference + by the simulation timestep. + + \note If a single suspension spring is hanging in the air and generates zero force the remaining springs of the vehicle will necessarily + sit in a compressed configuration. In summary, the sum of the remaining suspension forces cannot balance the downwards gravitational force + acting on the vehicle without extra force arising from the deltaX*mSpringStrength force term. + + \note Theoretically, a suspension spring should generate zero force at maximum elongation and increase linearly as the suspension approaches the rest pose. + PxVehicleSuspensionData will only enforce this physical law if the spring is configured so that |gravity|*mSprungMass == mMaxDroop*mSpringStrength. + To help decouple vehicle handling from visual wheel positioning this condition is not enforced. + In practice, the value of |gravity|*mSprungMass + deltaX*mSpringStrength is clamped at zero to ensure it never falls negative. + + @see PxVehicleComputeSprungMasses, PxVehicleWheelsSimData::setWheelCentreOffset, PxVehicleSuspensionData::mSpringStrength, PxVehicleSuspensionData::mSpringDamperRate, PxVehicleSuspensionData::mMaxDroop + + Range: [0, PX_MAX_F32)
+ */ + PxReal mSprungMass; + + /** + \brief Camber angle (in radians) of wheel when the suspension is at its rest position. + + \note Specified in radians. + + Range: [-pi/2, pi/2]
+ + */ + PxReal mCamberAtRest; + + /** + \brief Camber angle (in radians) of wheel when the suspension is at maximum compression. + + \note For compressed suspensions the camber angle is a linear interpolation of + mCamberAngleAtRest and mCamberAtMaxCompression + + \note Specified in radians. + + Range: [-pi/2, pi/2]
+ */ + PxReal mCamberAtMaxCompression; + + /** + \brief Camber angle (in radians) of wheel when the suspension is at maximum droop. + + \note For extended suspensions the camber angle is linearly interpolation of + mCamberAngleAtRest and mCamberAtMaxDroop + + \note Specified in radians. + + Range: [-pi/2, pi/2]
+ */ + PxReal mCamberAtMaxDroop; + + /** + \brief Reciprocal of maximum compression. + + \note Not necessary to set this value because it is set by PxVehicleWheelsSimData::setSuspensionData + + Range: [0, PX_MAX_F32)
+ */ + PX_FORCE_INLINE PxReal getRecipMaxCompression() const {return mRecipMaxCompression;} + + /** + \brief Reciprocal of maximum droop. + + \note Not necessary to set this value because it is set by PxVehicleWheelsSimData::setSuspensionData + + Range: [0, PX_MAX_F32)
+ */ + PX_FORCE_INLINE PxReal getRecipMaxDroop() const {return mRecipMaxDroop;} + + /** + \brief Set a new sprung mass for the suspension and modify the spring strength so that the natural frequency + of the spring is preserved. + \param[in] newSprungMass is the new mass that the suspension spring will support. + */ + void setMassAndPreserveNaturalFrequency(const PxReal newSprungMass) + { + const PxF32 oldStrength = mSpringStrength; + const PxF32 oldSprungMass = mSprungMass; + const PxF32 newStrength = oldStrength * (newSprungMass / oldSprungMass); + mSpringStrength = newStrength; + mSprungMass = newSprungMass; + } + +private: + + /** + \brief Cached value of 1.0f/mMaxCompression + + \note Not necessary to set this value because it is set by PxVehicleWheelsSimData::setSuspensionData + */ + PxReal mRecipMaxCompression; + + /** + \brief Cached value of 1.0f/mMaxDroop + + \note Not necessary to set this value because it is set by PxVehicleWheelsSimData::setSuspensionData + */ + PxReal mRecipMaxDroop; + + //padding + PxReal mPad[2]; + + bool isValid() const; +}; +PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleSuspensionData)& 0x0f)); + +class PxVehicleAntiRollBarData +{ +public: + + friend class PxVehicleWheelsSimData; + + PxVehicleAntiRollBarData() + : mWheel0(0xffffffff), + mWheel1(0xffffffff), + mStiffness(0.0f) + { + } + + /* + \brief The anti-roll bar connects two wheels with indices mWheel0 and mWheel1 + */ + PxU32 mWheel0; + + /* + \brief The anti-roll bar connects two wheels with indices mWheel0 and mWheel1 + */ + PxU32 mWheel1; + + /* + \brief The stiffness of the anti-roll bar. + + \note Specified in kilograms per second-squared (kg s^-2). + + Range: [0, PX_MAX_F32)
+ */ + PxF32 mStiffness; + +private: + + PxF32 mPad[1]; + + bool isValid() const; +}; +PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleAntiRollBarData)& 0x0f)); + +class PxVehicleTireData +{ +public: + friend class PxVehicleWheels4SimData; + + PxVehicleTireData() + : mLatStiffX(2.0f), + mLatStiffY(0.3125f*(180.0f / PxPi)), + mLongitudinalStiffnessPerUnitGravity(1000.0f), + mCamberStiffnessPerUnitGravity(0.1f*(180.0f / PxPi)), + mType(0) + { + mFrictionVsSlipGraph[0][0]=0.0f; + mFrictionVsSlipGraph[0][1]=1.0f; + mFrictionVsSlipGraph[1][0]=0.1f; + mFrictionVsSlipGraph[1][1]=1.0f; + mFrictionVsSlipGraph[2][0]=1.0f; + mFrictionVsSlipGraph[2][1]=1.0f; + + mRecipLongitudinalStiffnessPerUnitGravity=1.0f/mLongitudinalStiffnessPerUnitGravity; + + mFrictionVsSlipGraphRecipx1Minusx0=1.0f/(mFrictionVsSlipGraph[1][0]-mFrictionVsSlipGraph[0][0]); + mFrictionVsSlipGraphRecipx2Minusx1=1.0f/(mFrictionVsSlipGraph[2][0]-mFrictionVsSlipGraph[1][0]); + } + + /** + \brief Tire lateral stiffness is a graph of tire load that has linear behavior near zero load and + flattens at large loads. mLatStiffX describes the minimum normalized load (load/restLoad) that gives a + flat lateral stiffness response to load. + + Range: [0, PX_MAX_F32)
+ */ + PxReal mLatStiffX; + + /** + \brief Tire lateral stiffness is a graph of tire load that has linear behavior near zero load and + flattens at large loads. mLatStiffY describes the maximum possible value of lateralStiffness/restLoad that occurs + when (load/restLoad)>= mLatStiffX. + + \note If load/restLoad is greater than mLatStiffX then the lateral stiffness is mLatStiffY*restLoad. + + \note If load/restLoad is less than mLatStiffX then the lateral stiffness is mLastStiffY*(load/mLatStiffX) + + \note Lateral force can be approximated as lateralStiffness * lateralSlip. + + \note Specified in per radian. + + Range: [0, PX_MAX_F32)
+ */ + PxReal mLatStiffY; + + /** + \brief Tire Longitudinal stiffness per unit gravitational acceleration. + + \note Longitudinal stiffness of the tire is calculated as gravitationalAcceleration*mLongitudinalStiffnessPerUnitGravity. + + \note Longitudinal force can be approximated as gravitationalAcceleration*mLongitudinalStiffnessPerUnitGravity*longitudinalSlip. + + \note Specified in kilograms per radian. + + Range: [0, PX_MAX_F32)
+ */ + PxReal mLongitudinalStiffnessPerUnitGravity; + + /** + \brief tire Tire camber stiffness per unity gravitational acceleration. + + \note Camber stiffness of the tire is calculated as gravitationalAcceleration*mCamberStiffnessPerUnitGravity + + \note Camber force can be approximated as gravitationalAcceleration*mCamberStiffnessPerUnitGravity*camberAngle. + + \note Specified in kilograms per radian. + + Range: [0, PX_MAX_F32)
+ */ + PxReal mCamberStiffnessPerUnitGravity; + + /** + \brief Graph of friction vs longitudinal slip with 3 points. + + \note mFrictionVsSlipGraph[0][0] is always zero. + + \note mFrictionVsSlipGraph[0][1] is the friction available at zero longitudinal slip. + + \note mFrictionVsSlipGraph[1][0] is the value of longitudinal slip with maximum friction. + + \note mFrictionVsSlipGraph[1][1] is the maximum friction. + + \note mFrictionVsSlipGraph[2][0] is the end point of the graph. + + \note mFrictionVsSlipGraph[2][1] is the value of friction for slips greater than mFrictionVsSlipGraph[2][0]. + + \note The friction value computed from the friction vs longitudinal slip graph is used to scale the friction + value for the combination of material and tire type (PxVehicleDrivableSurfaceToTireFrictionPairs). + + \note mFrictionVsSlipGraph[2][0] > mFrictionVsSlipGraph[1][0] > mFrictionVsSlipGraph[0][0] + + \note mFrictionVsSlipGraph[1][1] is typically greater than mFrictionVsSlipGraph[0][1] + + \note mFrictionVsSlipGraph[2][1] is typically smaller than mFrictionVsSlipGraph[1][1] + + \note longitudinal slips > mFrictionVsSlipGraph[2][0] use friction multiplier mFrictionVsSlipGraph[2][1] + + \note The final friction value used by the tire model is the value returned by PxVehicleDrivableSurfaceToTireFrictionPairs + multiplied by the value computed from mFrictionVsSlipGraph. + + @see PxVehicleDrivableSurfaceToTireFrictionPairs, PxVehicleComputeTireForce + + Range: [0, PX_MAX_F32)
+ */ + PxReal mFrictionVsSlipGraph[3][2]; + + /** + \brief Tire type denoting slicks, wets, snow, winter, summer, all-terrain, mud etc. + + @see PxVehicleDrivableSurfaceToTireFrictionPairs + + Range: [0, PX_MAX_F32)
+ */ + PxU32 mType; + + /** + \brief Return Cached value of 1.0/mLongitudinalStiffnessPerUnitGravity + + @see PxVehicleWheelsSimData::setTireData + */ + PX_FORCE_INLINE PxReal getRecipLongitudinalStiffnessPerUnitGravity() const {return mRecipLongitudinalStiffnessPerUnitGravity;} + + /** + \brief Return Cached value of 1.0f/(mFrictionVsSlipGraph[1][0]-mFrictionVsSlipGraph[0][0]) + + @see PxVehicleWheelsSimData::setTireData + */ + PX_FORCE_INLINE PxReal getFrictionVsSlipGraphRecipx1Minusx0() const {return mFrictionVsSlipGraphRecipx1Minusx0;} + + /** + \brief Return Cached value of 1.0f/(mFrictionVsSlipGraph[2][0]-mFrictionVsSlipGraph[1][0]) + + @see PxVehicleWheelsSimData::setTireData + */ + PX_FORCE_INLINE PxReal getFrictionVsSlipGraphRecipx2Minusx1() const {return mFrictionVsSlipGraphRecipx2Minusx1;} + +private: + + /** + \brief Cached value of 1.0/mLongitudinalStiffnessPerUnitGravity. + + \note Not necessary to set this value because it is set by PxVehicleWheelsSimData::setTireData + + @see PxVehicleWheelsSimData::setTireData + */ + PxReal mRecipLongitudinalStiffnessPerUnitGravity; + + /** + \brief Cached value of 1.0f/(mFrictionVsSlipGraph[1][0]-mFrictionVsSlipGraph[0][0]) + + \note Not necessary to set this value because it is set by PxVehicleWheelsSimData::setTireData + + @see PxVehicleWheelsSimData::setTireData + */ + PxReal mFrictionVsSlipGraphRecipx1Minusx0; + + /** + \brief Cached value of 1.0f/(mFrictionVsSlipGraph[2][0]-mFrictionVsSlipGraph[1][0]) + + \note Not necessary to set this value because it is set by PxVehicleWheelsSimData::setTireData + + @see PxVehicleWheelsSimData::setTireData + */ + PxReal mFrictionVsSlipGraphRecipx2Minusx1; + + PxReal mPad[2]; + + bool isValid() const; +}; +PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleTireData)& 0x0f)); +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif //PX_VEHICLE_CORE_COMPONENTS_H diff --git a/sources/PhysX/PhysX/include/vehicle/PxVehicleDrive.h b/sources/PhysX/PhysX/include/vehicle/PxVehicleDrive.h new file mode 100644 index 00000000..c0ca3fc6 --- /dev/null +++ b/sources/PhysX/PhysX/include/vehicle/PxVehicleDrive.h @@ -0,0 +1,565 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_VEHICLE_DRIVE_H +#define PX_VEHICLE_DRIVE_H +/** \addtogroup vehicle + @{ +*/ + +#include "vehicle/PxVehicleWheels.h" +#include "vehicle/PxVehicleComponents.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +struct PxFilterData; +class PxGeometry; +class PxPhysics; +class PxVehicleDrivableSurfaceToTireFrictionPairs; +class PxShape; +class PxMaterial; +class PxRigidDynamic; + +/** +\brief Data structure describing non-wheel configuration data of a vehicle that has engine, gears, clutch, and auto-box. +@see PxVehicleWheelsSimData for wheels configuration data. +*/ +class PxVehicleDriveSimData +{ +//= ATTENTION! ===================================================================================== +// Changing the data layout of this class breaks the binary serialization format. See comments for +// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData +// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION +// accordingly. +//================================================================================================== +public: + + friend class PxVehicleDriveTank; + + /** + \brief Return the engine data + */ + PX_FORCE_INLINE const PxVehicleEngineData& getEngineData() const + { + return mEngine; + } + + /** + \brief Set the engine data + \param[in] engine - the data stored in engine is copied to the vehicle's engine. + */ + void setEngineData(const PxVehicleEngineData& engine); + + /** + \brief Return the gears data + */ + PX_FORCE_INLINE const PxVehicleGearsData& getGearsData() const + { + return mGears; + } + + /** + \brief Set the gears data + \param[in] gears - the data stored in gears is copied to the vehicle's gears. + */ + void setGearsData(const PxVehicleGearsData& gears); + + /** + \brief Return the clutch data + */ + PX_FORCE_INLINE const PxVehicleClutchData& getClutchData() const + { + return mClutch; + } + + /** + \brief Set the clutch data + \param[in] clutch - the data stored in clutch is copied to the vehicle's clutch. + */ + void setClutchData(const PxVehicleClutchData& clutch); + + /** + \brief Return the autobox data + */ + PX_FORCE_INLINE const PxVehicleAutoBoxData& getAutoBoxData() const + { + return mAutoBox; + } + + /** + \brief Set the autobox data + \param[in] autobox - the data stored in autobox is copied to the vehicle's autobox. + */ + void setAutoBoxData(const PxVehicleAutoBoxData& autobox); + +protected: + /* + \brief Engine simulation data + @see setEngineData, getEngineData + */ + PxVehicleEngineData mEngine; + + /* + \brief Gear simulation data + @see setGearsData, getGearsData + */ + PxVehicleGearsData mGears; + + /* + \brief Clutch simulation data + @see setClutchData, getClutchData + */ + PxVehicleClutchData mClutch; + + /* + \brief Autobox simulation data + @see setAutoboxData, getAutoboxData + */ + PxVehicleAutoBoxData mAutoBox; + + /** + \brief Test that a PxVehicleDriveSimData instance has been configured with legal data. + Call only after setting all components with setEngineData,setGearsData,setClutchData,setAutoBoxData + @see PxVehicleDrive4W::setup, PxVehicleDriveTank::setup + */ + bool isValid() const; + + +//serialization +public: + PxVehicleDriveSimData() {} + PxVehicleDriveSimData(const PxEMPTY) : mEngine(PxEmpty), mGears(PxEmpty), mClutch(PxEmpty), mAutoBox(PxEmpty) {} + static void getBinaryMetaData(PxOutputStream& stream); +//~serialization +}; +PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleDriveSimData) & 15)); + + +/** +\brief Data structure with instanced dynamics data for vehicle with engine, clutch, gears, autobox +@see PxVehicleWheelsDynData for wheels dynamics data. +*/ +class PxVehicleDriveDynData +{ +public: + + enum + { + eMAX_NB_ANALOG_INPUTS=16 + }; + + friend class PxVehicleDrive; + + /** + \brief Set all dynamics data to zero to bring the vehicle to rest. + */ + void setToRestState(); + + /** + \brief Set an analog control value to drive the vehicle. + \param[in] type describes the type of analog control being modified + \param[in] analogVal is the new value of the specific analog control. + @see PxVehicleDrive4WControl, PxVehicleDriveNWControl, PxVehicleDriveTankControl + */ + void setAnalogInput(const PxU32 type, const PxReal analogVal); + + /** + \brief Get the analog control value that has been applied to the vehicle. + \return The value of the specified analog control value. + @see PxVehicleDrive4WControl, PxVehicleDriveNWControl, PxVehicleDriveTankControl + */ + PxReal getAnalogInput(const PxU32 type) const; + + /** + \brief Inform the vehicle that the gear-up button has been pressed. + + \param[in] digitalVal is the state of the gear-up button. + + \note If digitalVal is true the vehicle will attempt to initiate a gear change at the next call to PxVehicleUpdates. + + \note The value of mGearUpPressed is not reset by PxVehicleUpdates + */ + void setGearUp(const bool digitalVal) + { + mGearUpPressed = digitalVal; + } + + /** + \brief Set that the gear-down button has been pressed. + + \param[in] digitalVal is the state of the gear-down button. + + \note If digitalVal is true the vehicle will attempt to initiate a gear change at the next call to PxVehicleUpdates. + + \note The value of mGearDownPressed is not reset by PxVehicleUpdates + */ + void setGearDown(const bool digitalVal) + { + mGearDownPressed = digitalVal; + } + + /** + \brief Check if the gear-up button has been pressed + \return The state of the gear-up button. + */ + bool getGearUp() const + { + return mGearUpPressed; + } + + /** + \brief Check if the gear-down button has been pressed + \return The state of the gear-down button. + */ + bool getGearDown() const + { + return mGearDownPressed; + } + + /** + \brief Set the flag that will be used to select auto-gears + If useAutoGears is true the auto-box will be active. + \param[in] useAutoGears is the active state of the auto-box. + */ + PX_FORCE_INLINE void setUseAutoGears(const bool useAutoGears) + { + mUseAutoGears=useAutoGears; + } + + /** + \brief Get the flag status that is used to select auto-gears + \return The active status of the auto-box. + */ + PX_FORCE_INLINE bool getUseAutoGears() const + { + return mUseAutoGears; + } + + /** + \brief Toggle the auto-gears flag + If useAutoGears is true the auto-box will be active. + */ + PX_FORCE_INLINE void toggleAutoGears() + { + mUseAutoGears = !mUseAutoGears; + } + + /** + \brief Set the current gear. + + \param[in] currentGear is the vehicle's gear. + + \note If the target gear is different from the current gear the vehicle will + attempt to start a gear change from the current gear that has just been set + towards the target gear at the next call to PxVehicleUpdates. + + @see setTargetGear, PxVehicleGearsData + */ + PX_FORCE_INLINE void setCurrentGear(PxU32 currentGear) + { + mCurrentGear = currentGear; + } + + /** + \brief Get the current gear. + + \return The vehicle's current gear. + + @see getTargetGear, PxVehicleGearsData + */ + PX_FORCE_INLINE PxU32 getCurrentGear() const + { + return mCurrentGear; + } + + /** + \brief Set the target gear. + + \param[in] targetGear is the vehicle's target gear. + + \note If the target gear is different from the current gear the vehicle will + attempt to start a gear change towards the target gear at the next call to + PxVehicleUpdates. + + @see PxVehicleGearsData + */ + PX_FORCE_INLINE void setTargetGear(PxU32 targetGear) + { + mTargetGear = targetGear; + } + + /** + \brief Get the target gear. + + \return The vehicle's target gear. + + @see setTargetGear, PxVehicleGearsData + */ + PX_FORCE_INLINE PxU32 getTargetGear() const + { + return mTargetGear; + } + + /** + \brief Start a gear change to a target gear. + + \param[in] targetGear is the gear the vehicle will begin a transition towards. + + \note The gear change will begin at the next call to PxVehicleUpadates. + + @see PxVehicleGearsData + */ + PX_FORCE_INLINE void startGearChange(const PxU32 targetGear) + { + mTargetGear=targetGear; + } + + /** + \brief Force an immediate gear change to a target gear + + \param[in] targetGear is the gear the vehicle will be given immediately. + + @see PxVehicleGearsData + */ + PX_FORCE_INLINE void forceGearChange(const PxU32 targetGear) + { + mTargetGear=targetGear; + mCurrentGear=targetGear; + } + + /** + \brief Set the rotation speed of the engine (radians per second) + + \param[in] speed is the rotational speed (radians per second) to apply to the engine. + */ + PX_FORCE_INLINE void setEngineRotationSpeed(const PxF32 speed) + { + mEnginespeed = speed; + } + + /** + \brief Return the rotation speed of the engine (radians per second) + + \return The rotational speed (radians per second) of the engine. + */ + PX_FORCE_INLINE PxReal getEngineRotationSpeed() const + { + return mEnginespeed; + } + + /** + \brief Return the time that has passed since the current gear change was initiated. + + \return The time that has passed since the current gear change was initiated. + + \note If no gear change is in process the gear switch time will be zero. + + @see PxVehicleGearsData.mSwitchTime + */ + PX_FORCE_INLINE PxReal getGearSwitchTime() const + { + return mGearSwitchTime; + } + + /** + \brief Return the time that has passed since the autobox last initiated a gear change. + + \return The time that has passed since the autobox last initiated a gear change. + + @see PxVehicleAutoBoxData::setLatency, PxVehicleAutoBoxData::getLatency + */ + PX_FORCE_INLINE PxReal getAutoBoxSwitchTime() const + { + return mAutoBoxSwitchTime; + } + + /** + \brief All dynamic data values are public for fast access. + */ + + + /** + \brief Analog control values used by vehicle simulation. + @see setAnalogInput, getAnalogInput, PxVehicleDrive4WControl, PxVehicleDriveNWControl, PxVehicleDriveTankControl + */ + PxReal mControlAnalogVals[eMAX_NB_ANALOG_INPUTS]; + + /** + \brief Auto-gear flag used by vehicle simulation. Set true to enable the autobox, false to disable the autobox. + @see setUseAutoGears, setUseAutoGears, toggleAutoGears, PxVehicleAutoBoxData + */ + bool mUseAutoGears; + + /** + \brief Gear-up digital control value used by vehicle simulation. + + \note If true a gear change will be initiated towards currentGear+1 (or to first gear if in reverse). + + @see setDigitalInput, getDigitalInput + */ + bool mGearUpPressed; + + /** + \brief Gear-down digital control value used by vehicle simulation. + + \note If true a gear change will be initiated towards currentGear-1 (or to reverse if in first). + + @see setDigitalInput, getDigitalInput + */ + bool mGearDownPressed; + + /** + \brief Current gear + @see startGearChange, forceGearChange, getCurrentGear, PxVehicleGearsData + */ + PxU32 mCurrentGear; + + /** + \brief Target gear (different from current gear if a gear change is underway) + @see startGearChange, forceGearChange, getTargetGear, PxVehicleGearsData + */ + PxU32 mTargetGear; + + /** + \brief Rotation speed of engine + @see setToRestState, getEngineRotationSpeed + */ + PxReal mEnginespeed; + + /** + \brief Reported time that has passed since gear change started. + @see setToRestState, startGearChange, PxVehicleGearsData::mSwitchTime + */ + PxReal mGearSwitchTime; + + /** + \brief Reported time that has passed since last autobox gearup/geardown decision. + @see setToRestState, PxVehicleAutoBoxData::setLatency + */ + PxReal mAutoBoxSwitchTime; + +private: + PxU32 mPad[2]; + + /** + \brief Test that a PxVehicleDriveDynData instance has legal values. + @see setToRestState + */ + bool isValid() const; + +//serialization +public: + PxVehicleDriveDynData(); + PxVehicleDriveDynData(const PxEMPTY) {} + PxU32 getNbAnalogInput() const { return eMAX_NB_ANALOG_INPUTS; } + PX_FORCE_INLINE void setGearChange(const PxU32 gearChange) { mTargetGear= gearChange; } + PX_FORCE_INLINE PxU32 getGearChange() const { return mTargetGear; } + PX_FORCE_INLINE void setGearSwitchTime(const PxReal switchTime) { mGearSwitchTime = switchTime; } + PX_FORCE_INLINE void setAutoBoxSwitchTime(const PxReal autoBoxSwitchTime) { mAutoBoxSwitchTime = autoBoxSwitchTime; } +//~serialization +}; +PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleDriveDynData) & 15)); + +/** +\brief A complete vehicle with instance dynamics data and configuration data for wheels and engine,clutch,gears,autobox. +@see PxVehicleDrive4W, PxVehicleDriveTank +*/ +class PxVehicleDrive : public PxVehicleWheels +{ +//= ATTENTION! ===================================================================================== +// Changing the data layout of this class breaks the binary serialization format. See comments for +// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData +// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION +// accordingly. +//================================================================================================== +public: + + friend class PxVehicleUpdate; + + /** + \brief Dynamics data of vehicle instance. + @see setup + */ + PxVehicleDriveDynData mDriveDynData; + +protected: + + /** + \brief Test that all instanced dynamics data and configuration data have legal values. + */ + bool isValid() const; + + /** + \brief Set vehicle to rest. + */ + void setToRestState(); + + /** + @see PxVehicleDrive4W::allocate, PxVehicleDriveTank::allocate + */ + static PxU32 computeByteSize(const PxU32 numWheels); + static PxU8* patchupPointers(const PxU32 nbWheels, PxVehicleDrive* vehDrive, PxU8* ptr); + virtual void init(const PxU32 numWheels); + + /** + \brief Deallocate a PxVehicle4WDrive instance. + @see PxVehicleDrive4W::free, PxVehicleDriveTank::free + */ + void free(); + + /** + @see PxVehicleDrive4W::setup, PxVehicleDriveTank::setup + */ + void setup + (PxPhysics* physics, PxRigidDynamic* vehActor, + const PxVehicleWheelsSimData& wheelsData, + const PxU32 nbDrivenWheels, const PxU32 nbNonDrivenWheels); + +//serialization +public: + static void getBinaryMetaData(PxOutputStream& stream); + PxVehicleDrive(PxBaseFlags baseFlags) : PxVehicleWheels(baseFlags), mDriveDynData(PxEmpty) {} + virtual const char* getConcreteTypeName() const { return "PxVehicleDrive"; } +protected: + PxVehicleDrive(PxType concreteType, PxBaseFlags baseFlags) : PxVehicleWheels(concreteType, baseFlags) {} + ~PxVehicleDrive() {} + virtual bool isKindOf(const char* name) const { return !::strcmp("PxVehicleDrive", name) || PxBase::isKindOf(name); } +//~serialization +}; +PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleDrive) & 15)); + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif //PX_VEHICLE_DRIVE_H diff --git a/sources/PhysX/PhysX/include/vehicle/PxVehicleDrive4W.h b/sources/PhysX/PhysX/include/vehicle/PxVehicleDrive4W.h new file mode 100644 index 00000000..270f1662 --- /dev/null +++ b/sources/PhysX/PhysX/include/vehicle/PxVehicleDrive4W.h @@ -0,0 +1,278 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_VEHICLE_4WDRIVE_H +#define PX_VEHICLE_4WDRIVE_H +/** \addtogroup vehicle + @{ +*/ + +#include "vehicle/PxVehicleDrive.h" +#include "vehicle/PxVehicleWheels.h" +#include "vehicle/PxVehicleComponents.h" + + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +struct PxFilterData; +class PxGeometry; +class PxPhysics; +class PxVehicleDrivableSurfaceToTireFrictionPairs; +class PxShape; +class PxMaterial; +class PxRigidDynamic; + +/** +\brief Data structure describing the drive model components of a vehicle with up to 4 driven wheels and up to 16 un-driven wheels. +The drive model incorporates engine, clutch, gears, autobox, differential, and Ackermann steer correction. +@see PxVehicleDriveSimData +*/ +class PxVehicleDriveSimData4W : public PxVehicleDriveSimData +{ +//= ATTENTION! ===================================================================================== +// Changing the data layout of this class breaks the binary serialization format. See comments for +// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData +// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION +// accordingly. +//================================================================================================== +public: + + friend class PxVehicleDrive4W; + + PxVehicleDriveSimData4W() + : PxVehicleDriveSimData() + { + } + + /** + \brief Return the data describing the differential. + @see PxVehicleDifferential4WData + */ + PX_FORCE_INLINE const PxVehicleDifferential4WData& getDiffData() const + { + return mDiff; + } + + /** + \brief Return the data describing the Ackermann steer-correction. + @see PxVehicleAckermannGeometryData + */ + PX_FORCE_INLINE const PxVehicleAckermannGeometryData& getAckermannGeometryData() const + { + return mAckermannGeometry; + } + + /** + \brief Set the data describing the differential. + @see PxVehicleDifferential4WData + */ + void setDiffData(const PxVehicleDifferential4WData& diff); + + /** + \brief Set the data describing the Ackermann steer-correction. + @see PxVehicleAckermannGeometryData + */ + void setAckermannGeometryData(const PxVehicleAckermannGeometryData& ackermannData); + +private: + + /** + \brief Differential simulation data + @see setDiffData, getDiffData + */ + PxVehicleDifferential4WData mDiff; + + /** + \brief Data for ackermann steer angle computation. + @see setAckermannGeometryData, getAckermannGeometryData + */ + PxVehicleAckermannGeometryData mAckermannGeometry; + + /** + \brief Test if the 4W-drive simulation data has been setup with legal data. + \note Call only after setting all components. + @see setEnginedata, setClutchData, setGearsData, setAutoboxData, setDiffData, setAckermannGeometryData + */ + bool isValid() const; + +//serialization +public: + PxVehicleDriveSimData4W(const PxEMPTY) : PxVehicleDriveSimData(PxEmpty), mDiff(PxEmpty), mAckermannGeometry(PxEmpty) {} + static void getBinaryMetaData(PxOutputStream& stream); +//~serialization +}; +PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleDriveSimData4W) & 15)); + + + +/** +\brief The ordering of the driven and steered wheels of a PxVehicleDrive4W. + +@see PxVehicleWheelsSimData, PxVehicleWheelsDynData +*/ + +struct PxVehicleDrive4WWheelOrder +{ + enum Enum + { + eFRONT_LEFT=0, + eFRONT_RIGHT, + eREAR_LEFT, + eREAR_RIGHT + }; +}; + +/** +\brief The control inputs for a PxVehicleDrive4W. + +@see PxVehicleDriveDynData::setAnalogInput, PxVehicleDriveDynData::getAnalogInput +*/ + +struct PxVehicleDrive4WControl +{ + enum Enum + { + eANALOG_INPUT_ACCEL=0, + eANALOG_INPUT_BRAKE, + eANALOG_INPUT_HANDBRAKE, + eANALOG_INPUT_STEER_LEFT, + eANALOG_INPUT_STEER_RIGHT, + eMAX_NB_DRIVE4W_ANALOG_INPUTS + }; +}; + +/** +\brief Data structure with instanced dynamics data and configuration data of a vehicle with up to 4 driven wheels and up to 16 non-driven wheels. +*/ +class PxVehicleDrive4W : public PxVehicleDrive +{ +//= ATTENTION! ===================================================================================== +// Changing the data layout of this class breaks the binary serialization format. See comments for +// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData +// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION +// accordingly. +//================================================================================================== +public: + friend class PxVehicleUpdate; + + /** + \brief Allocate a PxVehicleDrive4W instance for a 4WDrive vehicle with nbWheels (= 4 + number of un-driven wheels) + + \param[in] nbWheels is the number of vehicle wheels (= 4 + number of un-driven wheels) + + \return The instantiated vehicle. + + @see free, setup + */ + static PxVehicleDrive4W* allocate(const PxU32 nbWheels); + + /** + \brief Deallocate a PxVehicleDrive4W instance. + @see allocate + */ + void free(); + + /** + \brief Set up a vehicle using simulation data for the wheels and drive model. + \param[in] physics is a PxPhysics instance that is needed to create special vehicle constraints that are maintained by the vehicle. + \param[in] vehActor is a PxRigidDynamic instance that is used to represent the vehicle in the PhysX SDK. + \param[in] wheelsData describes the configuration of all suspension/tires/wheels of the vehicle. The vehicle instance takes a copy of this data. + \param[in] driveData describes the properties of the vehicle's drive model (gears/engine/clutch/differential/autobox). The vehicle instance takes a copy of this data. + \param[in] nbNonDrivenWheels is the number of wheels on the vehicle that cannot be connected to the differential (= numWheels - 4). + \note It is assumed that the first shapes of the actor are the wheel shapes, followed by the chassis shapes. To break this assumption use PxVehicleWheelsSimData::setWheelShapeMapping. + \note wheelsData must contain data for at least 4 wheels. Unwanted wheels can be disabled with PxVehicleWheelsSimData::disableWheel after calling setup. + @see allocate, free, setToRestState, PxVehicleWheelsSimData::setWheelShapeMapping + */ + void setup + (PxPhysics* physics, PxRigidDynamic* vehActor, + const PxVehicleWheelsSimData& wheelsData, const PxVehicleDriveSimData4W& driveData, + const PxU32 nbNonDrivenWheels); + + /** + \brief Allocate and set up a vehicle using simulation data for the wheels and drive model. + \param[in] physics is a PxPhysics instance that is needed to create special vehicle constraints that are maintained by the vehicle. + \param[in] vehActor is a PxRigidDynamic instance that is used to represent the vehicle in the PhysX SDK. + \param[in] wheelsData describes the configuration of all suspension/tires/wheels of the vehicle. The vehicle instance takes a copy of this data. + \param[in] driveData describes the properties of the vehicle's drive model (gears/engine/clutch/differential/autobox). The vehicle instance takes a copy of this data. + \param[in] nbNonDrivenWheels is the number of wheels on the vehicle that cannot be connected to the differential (= numWheels - 4). + \note It is assumed that the first shapes of the actor are the wheel shapes, followed by the chassis shapes. To break this assumption use PxVehicleWheelsSimData::setWheelShapeMapping. + \note wheelsData must contain data for at least 4 wheels. Unwanted wheels can be disabled with PxVehicleWheelsSimData::disableWheel after calling setup. + \return The instantiated vehicle. + @see allocate, free, setToRestState, PxVehicleWheelsSimData::setWheelShapeMapping + */ + static PxVehicleDrive4W* create + (PxPhysics* physics, PxRigidDynamic* vehActor, + const PxVehicleWheelsSimData& wheelsData, const PxVehicleDriveSimData4W& driveData, + const PxU32 nbNonDrivenWheels); + + /** + \brief Set a vehicle to its rest state. Aside from the rigid body transform, this will set the vehicle and rigid body + to the state they were in immediately after setup or create. + \note Calling setToRestState invalidates the cached raycast hit planes under each wheel meaning that suspension line + raycasts need to be performed at least once with PxVehicleSuspensionRaycasts before calling PxVehicleUpdates. + @see setup, create, PxVehicleSuspensionRaycasts, PxVehicleUpdates + */ + void setToRestState(); + + /** + \brief Simulation data that describes the configuration of the vehicle's drive model. + @see setup, create + */ + PxVehicleDriveSimData4W mDriveSimData; + +private: + + /** + \brief Test if the instanced dynamics and configuration data has legal values. + */ + bool isValid() const; + +//serialization +protected: + PxVehicleDrive4W(); + ~PxVehicleDrive4W(){} + virtual bool isKindOf(const char* name) const { return !::strcmp("PxVehicleDrive4W", name) || PxBase::isKindOf(name); } +public: + static PxVehicleDrive4W* createObject(PxU8*& address, PxDeserializationContext& context); + static void getBinaryMetaData(PxOutputStream& stream); + PxVehicleDrive4W(PxBaseFlags baseFlags) : PxVehicleDrive(baseFlags), mDriveSimData(PxEmpty) {} + virtual const char* getConcreteTypeName() const { return "PxVehicleDrive4W"; } +//~serialization +}; +PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleDrive4W) & 15)); + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif //PX_VEHICLE_4WDRIVE_H diff --git a/sources/PhysX/PhysX/include/vehicle/PxVehicleDriveNW.h b/sources/PhysX/PhysX/include/vehicle/PxVehicleDriveNW.h new file mode 100644 index 00000000..f9334d2a --- /dev/null +++ b/sources/PhysX/PhysX/include/vehicle/PxVehicleDriveNW.h @@ -0,0 +1,236 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_VEHICLE_NWDRIVE_H +#define PX_VEHICLE_NWDRIVE_H +/** \addtogroup vehicle + @{ +*/ + +#include "vehicle/PxVehicleDrive.h" +#include "vehicle/PxVehicleWheels.h" +#include "vehicle/PxVehicleComponents.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +struct PxFilterData; +class PxGeometry; +class PxPhysics; +class PxVehicleDrivableSurfaceToTireFrictionPairs; +class PxShape; +class PxMaterial; +class PxRigidDynamic; + +/** +\brief Data structure describing configuration data of a vehicle with up to PX_MAX_NB_WHEELS driven equally through the differential. The vehicle has an +engine, clutch, gears, autobox, differential. +@see PxVehicleDriveSimData +*/ +class PxVehicleDriveSimDataNW : public PxVehicleDriveSimData +{ +//= ATTENTION! ===================================================================================== +// Changing the data layout of this class breaks the binary serialization format. See comments for +// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData +// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION +// accordingly. +//================================================================================================== +public: + + friend class PxVehicleDriveNW; + + PxVehicleDriveSimDataNW() + : PxVehicleDriveSimData() + { + } + + /** + \brief Return the data describing the differential of a vehicle with up to PX_MAX_NB_WHEELS driven wheels. + */ + const PxVehicleDifferentialNWData& getDiffData() const + { + return mDiff; + } + + /** + \brief Set the data describing the differential of a vehicle with up to PX_MAX_NB_WHEELS driven wheels. + The differential data describes the set of wheels that are driven by the differential. + */ + void setDiffData(const PxVehicleDifferentialNWData& diff); + +private: + + /** + \brief Differential simulation data + @see setDiffData, getDiffData + */ + PxVehicleDifferentialNWData mDiff; + + /** + \brief Test if the NW-drive simulation data has been setup with legal data. + Call only after setting all components. + @see setEngineData, setClutchData, setGearsData, setAutoboxData, setDiffData, setAckermannGeometryData + */ + bool isValid() const; + +//serialization +public: + PxVehicleDriveSimDataNW(const PxEMPTY) : PxVehicleDriveSimData(PxEmpty), mDiff(PxEmpty) {} + static void getBinaryMetaData(PxOutputStream& stream); +//~serialization +}; +PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleDriveSimDataNW) & 15)); + + +/** +\brief The control inputs for a PxVehicleDriveNW. + +@see PxVehicleDriveDynData::setAnalogInput, PxVehicleDriveDynData::getAnalogInput +*/ +struct PxVehicleDriveNWControl +{ + enum Enum + { + eANALOG_INPUT_ACCEL=0, + eANALOG_INPUT_BRAKE, + eANALOG_INPUT_HANDBRAKE, + eANALOG_INPUT_STEER_LEFT, + eANALOG_INPUT_STEER_RIGHT, + eMAX_NB_DRIVENW_ANALOG_INPUTS + }; +}; + +/** +\brief Data structure with instanced dynamics data and configuration data of a vehicle with up to PX_MAX_NB_WHEELS driven wheels. +*/ +class PxVehicleDriveNW : public PxVehicleDrive +{ +//= ATTENTION! ===================================================================================== +// Changing the data layout of this class breaks the binary serialization format. See comments for +// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData +// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION +// accordingly. +//================================================================================================== +public: + + friend class PxVehicleUpdate; + + /** + \brief Allocate a PxVehicleDriveNW instance for a NWDrive vehicle with nbWheels + + \param[in] nbWheels is the number of wheels on the vehicle. + + \return The instantiated vehicle. + + @see free, setup + */ + static PxVehicleDriveNW* allocate(const PxU32 nbWheels); + + /** + \brief Deallocate a PxVehicleDriveNW instance. + @see allocate + */ + void free(); + + /** + \brief Set up a vehicle using simulation data for the wheels and drive model. + \param[in] physics is a PxPhysics instance that is needed to create special vehicle constraints that are maintained by the vehicle. + \param[in] vehActor is a PxRigidDynamic instance that is used to represent the vehicle in the PhysX SDK. + \param[in] wheelsData describes the configuration of all suspension/tires/wheels of the vehicle. The vehicle instance takes a copy of this data. + \param[in] driveData describes the properties of the vehicle's drive model (gears/engine/clutch/differential/autobox). The vehicle instance takes a copy of this data. + \param[in] nbWheels is the number of wheels on the vehicle. + \note It is assumed that the first shapes of the actor are the wheel shapes, followed by the chassis shapes. To break this assumption use PxVehicleWheelsSimData::setWheelShapeMapping. + @see allocate, free, setToRestState, PxVehicleWheelsSimData::setWheelShapeMapping + */ + void setup + (PxPhysics* physics, PxRigidDynamic* vehActor, + const PxVehicleWheelsSimData& wheelsData, const PxVehicleDriveSimDataNW& driveData, + const PxU32 nbWheels); + + /** + \brief Allocate and set up a vehicle using simulation data for the wheels and drive model. + \param[in] physics is a PxPhysics instance that is needed to create special vehicle constraints that are maintained by the vehicle. + \param[in] vehActor is a PxRigidDynamic instance that is used to represent the vehicle in the PhysX SDK. + \param[in] wheelsData describes the configuration of all suspension/tires/wheels of the vehicle. The vehicle instance takes a copy of this data. + \param[in] driveData describes the properties of the vehicle's drive model (gears/engine/clutch/differential/autobox). The vehicle instance takes a copy of this data. + \param[in] nbWheels is the number of wheels on the vehicle. + \note It is assumed that the first shapes of the actor are the wheel shapes, followed by the chassis shapes. To break this assumption use PxVehicleWheelsSimData::setWheelShapeMapping. + \return The instantiated vehicle. + @see allocate, free, setToRestState, PxVehicleWheelsSimData::setWheelShapeMapping + */ + static PxVehicleDriveNW* create + (PxPhysics* physics, PxRigidDynamic* vehActor, + const PxVehicleWheelsSimData& wheelsData, const PxVehicleDriveSimDataNW& driveData, + const PxU32 nbWheels); + + /** + \brief Set a vehicle to its rest state. Aside from the rigid body transform, this will set the vehicle and rigid body + to the state they were in immediately after setup or create. + \note Calling setToRestState invalidates the cached raycast hit planes under each wheel meaning that suspension line + raycasts need to be performed at least once with PxVehicleSuspensionRaycasts before calling PxVehicleUpdates. + @see setup, create, PxVehicleSuspensionRaycasts, PxVehicleUpdates + */ + void setToRestState(); + + /** + \brief Simulation data that describes the configuration of the vehicle's drive model. + @see setup, create + */ + PxVehicleDriveSimDataNW mDriveSimData; + +private: + + /** + \brief Test if the instanced dynamics and configuration data has legal values. + */ + bool isValid() const; + +//serialization +public: + PxVehicleDriveNW(PxBaseFlags baseFlags) : PxVehicleDrive(baseFlags), mDriveSimData(PxEmpty) {} + PxVehicleDriveNW(); + ~PxVehicleDriveNW(){} + static PxVehicleDriveNW* createObject(PxU8*& address, PxDeserializationContext& context); + static void getBinaryMetaData(PxOutputStream& stream); + virtual const char* getConcreteTypeName() const { return "PxVehicleDriveNW"; } + virtual bool isKindOf(const char* name) const { return !::strcmp("PxVehicleDriveNW", name) || PxBase::isKindOf(name); } +//~serialization +}; +PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleDriveNW) & 15)); + + + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif //PX_VEHICLE_NWDRIVE_H diff --git a/sources/PhysX/PhysX/include/vehicle/PxVehicleDriveTank.h b/sources/PhysX/PhysX/include/vehicle/PxVehicleDriveTank.h new file mode 100644 index 00000000..b9f16351 --- /dev/null +++ b/sources/PhysX/PhysX/include/vehicle/PxVehicleDriveTank.h @@ -0,0 +1,280 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_VEHICLE_DRIVE_TANK_H +#define PX_VEHICLE_DRIVE_TANK_H +/** \addtogroup vehicle + @{ +*/ + +#include "vehicle/PxVehicleDrive.h" +#include "vehicle/PxVehicleWheels.h" +#include "vehicle/PxVehicleComponents.h" + + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +struct PxFilterData; +class PxGeometry; +class PxPhysics; +class PxVehicleDrivableSurfaceToTireFrictionPairs; +class PxShape; +class PxMaterial; +class PxRigidDynamic; + +/** +\brief The ordering of the wheels of a PxVehicleDriveTank. + +@see PxVehicleWheelsSimData, PxVehicleWheelsDynData +*/ +struct PxVehicleDriveTankWheelOrder +{ + enum Enum + { + eFRONT_LEFT=0, + eFRONT_RIGHT, + e1ST_FROM_FRONT_LEFT, + e1ST_FROM_FRONT_RIGHT, + e2ND_FROM_FRONT_LEFT, + e2ND_FROM_FRONT_RIGHT, + e3RD_FROM_FRONT_LEFT, + e3RD_FROM_FRONT_RIGHT, + e4TH_FROM_FRONT_LEFT, + e4TH_FROM_FRONT_RIGHT, + e5TH_FROM_FRONT_LEFT, + e5TH_FROM_FRONT_RIGHT, + e6TH_FROM_FRONT_LEFT, + e6TH_FROM_FRONT_RIGHT, + e7TH_FROM_FRONT_LEFT, + e7TH_FROM_FRONT_RIGHT, + e8TH_FROM_FRONT_LEFT, + e8TH_FROM_FRONT_RIGHT, + e9TH_FROM_FRONT_LEFT, + e9TH_FROM_FRONT_RIGHT + }; +}; + + +/** +\brief The control inputs for a PxVehicleDriveTank. + +\note The values of eANALOG_INPUT_THRUST_LEFT and eANALOG_INPUT_THRUST_RIGHT determine how much +of the total available drive torque is diverted to the left and right wheels. These entries in the +enumerated list represent the state of the left and right control sticks of a tank. The total available +drive torque available is controlled by eANALOG_INPUT_ACCEL, which represents the state of the acceleration +pedal and controls how much torque will be applied to the engine. + +\note To accelerate forwards eANALOG_INPUT_ACCEL must be greater than zero so that torque is applied to drive the +engine, while eANALOG_INPUT_THRUST_LEFT and eANALOG_INPUT_THRUST_RIGHT must also be greater than zero +to divert the available drive torque to the left and wheels. If eANALOG_INPUT_THRUST_LEFT > eANALOG_INPUT_THRUST_RIGHT +the tank will turn to the right. If eANALOG_INPUT_THRUST_RIGHT > eANALOG_INPUT_THRUST_LEFT +the tank will turn to the left. + +@see PxVehicleDriveDynData::setAnalogInput, PxVehicleDriveDynData::getAnalogInput +*/ + +struct PxVehicleDriveTankControl +{ + enum Enum + { + eANALOG_INPUT_ACCEL=0, + eANALOG_INPUT_BRAKE_LEFT, + eANALOG_INPUT_BRAKE_RIGHT, + eANALOG_INPUT_THRUST_LEFT, + eANALOG_INPUT_THRUST_RIGHT, + eMAX_NB_DRIVETANK_ANALOG_INPUTS + }; +}; + +/** +\brief Two driving models are supported. + +\note If eSTANDARD is chosen the left and right wheels are always driven in the same direction. If the tank is in +a forward gear the left and right wheels will all be driven forwards, while in reverse gear the left and right wheels +will all be driven backwards. With eSTANDARD the legal range of left and right thrust is (0,1). + +\note If eSPECIAL is chosen it is possible to drive the left and right wheels in different directions. +With eSPECIAL the legal range of left and right thrust is (-1,1). In forward(reverse) gear negative thrust values drive the wheels +backwards(forwards), while positive thrust values drives the wheels forwards(backwards). + +\note A sharp left turn can be achieved in eSTANDARD mode by braking with the left wheels and thrusting forward with the +right wheels. A smaller turning circle can theoretically be achieved in eSPECIAL mode by applying negative thrust to the left wheels and positive +thrust to the right wheels. + +\note In both modes the legal ranges of acceleration and left/right brake are all (0,1). + +@see PxVehicleDriveTank::setDriveModel +*/ +struct PxVehicleDriveTankControlModel +{ + enum Enum + { + eSTANDARD=0, + eSPECIAL + }; +}; + + +/** +\brief Data structure with instanced dynamics data and configuration data of a tank. +*/ +class PxVehicleDriveTank : public PxVehicleDrive +{ +//= ATTENTION! ===================================================================================== +// Changing the data layout of this class breaks the binary serialization format. See comments for +// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData +// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION +// accordingly. +//================================================================================================== +public: + + friend class PxVehicleUpdate; + + + /** + \brief Allocate a PxVehicleTankDrive instance for a tank with nbWheels + + \param[in] nbWheels is the number of wheels on the vehicle. + + \note It is assumed that all wheels are driven wheels. + + \return The instantiated vehicle. + + @see free, setup + */ + static PxVehicleDriveTank* allocate(const PxU32 nbWheels); + + /** + \brief Deallocate a PxVehicleDriveTank instance. + @see allocate + */ + void free(); + + /** + \brief Set up a tank using simulation data for the wheels and drive model. + \param[in] physics is a PxPhysics instance that is needed to create special vehicle constraints that are maintained by the vehicle. + \param[in] vehActor is a PxRigidDynamic instance that is used to represent the tank in the PhysX SDK. + \param[in] wheelsData describes the configuration of all suspension/tires/wheels of the tank. The tank instance takes a copy of this data. + \param[in] driveData describes the properties of the tank's drive model (gears/engine/clutch/autobox). The tank instance takes a copy of this data. + \param[in] nbDrivenWheels is the number of wheels on the tank. + \note It is assumed that the first shapes of the actor are the wheel shapes, followed by the chassis shapes. To break this assumption use PxVehicleWheelsSimData::setWheelShapeMapping. + @see allocate, free, setToRestState, PxVehicleWheelsSimData::setWheelShapeMapping + \note nbDrivenWheels must be an even number + \note The wheels must be arranged according to PxVehicleDriveTankWheelOrder; that is, + the even wheels are on the left side of the tank and the odd wheels are on the right side of the tank. + */ + void setup + (PxPhysics* physics, PxRigidDynamic* vehActor, + const PxVehicleWheelsSimData& wheelsData, const PxVehicleDriveSimData& driveData, + const PxU32 nbDrivenWheels); + + /** + \brief Allocate and set up a tank using simulation data for the wheels and drive model. + \param[in] physics is a PxPhysics instance that is needed to create special vehicle constraints that are maintained by the tank. + \param[in] vehActor is a PxRigidDynamic instance that is used to represent the tank in the PhysX SDK. + \param[in] wheelsData describes the configuration of all suspension/tires/wheels of the tank. The tank instance takes a copy of this data. + \param[in] driveData describes the properties of the tank's drive model (gears/engine/clutch/differential/autobox). The tank instance takes a copy of this data. + \param[in] nbDrivenWheels is the number of wheels on the tank. + \note It is assumed that the first shapes of the actor are the wheel shapes, followed by the chassis shapes. To break this assumption use PxVehicleWheelsSimData::setWheelShapeMapping. + \return The instantiated vehicle. + @see allocate, free, setToRestState, PxVehicleWheelsSimData::setWheelShapeMapping + */ + static PxVehicleDriveTank* create + (PxPhysics* physics, PxRigidDynamic* vehActor, + const PxVehicleWheelsSimData& wheelsData, const PxVehicleDriveSimData& driveData, + const PxU32 nbDrivenWheels); + + /** + \brief Set the control model used by the tank. + \note eDRIVE_MODEL_STANDARD: turning achieved by braking on one side, accelerating on the other side. + \note eDRIVE_MODEL_SPECIAL: turning achieved by accelerating forwards on one side, accelerating backwards on the other side. + \note The default value is eDRIVE_MODEL_STANDARD + */ + void setDriveModel(const PxVehicleDriveTankControlModel::Enum driveModel) + { + mDriveModel=driveModel; + } + + /** + \brief Return the control model used by the tank. + */ + PxVehicleDriveTankControlModel::Enum getDriveModel() const {return mDriveModel;} + + /** + \brief Set a vehicle to its rest state. Aside from the rigid body transform, this will set the vehicle and rigid body + to the state they were in immediately after setup or create. + \note Calling setToRestState invalidates the cached raycast hit planes under each wheel meaning that suspension line + raycasts need to be performed at least once with PxVehicleSuspensionRaycasts before calling PxVehicleUpdates. + @see setup, create, PxVehicleSuspensionRaycasts, PxVehicleUpdates + */ + void setToRestState(); + + /** + \brief Simulation data that models vehicle components + @see setup, create + */ + PxVehicleDriveSimData mDriveSimData; + +private: + /** + \brief Test if the instanced dynamics and configuration data has legal values. + */ + bool isValid() const; + + /** + \brief Drive model + @see setDriveModel, getDriveModel, PxVehicleDriveTankControlModel + */ + PxVehicleDriveTankControlModel::Enum mDriveModel; + + PxU32 mPad[3]; + +//serialization +public: + PxVehicleDriveTank(PxBaseFlags baseFlags) : PxVehicleDrive(baseFlags) {} + static PxVehicleDriveTank* createObject(PxU8*& address, PxDeserializationContext& context); + static void getBinaryMetaData(PxOutputStream& stream); + virtual const char* getConcreteTypeName() const { return "PxVehicleDriveTank"; } + virtual bool isKindOf(const char* name) const { return !::strcmp("PxVehicleDriveTank", name) || PxBase::isKindOf(name); } +protected: + PxVehicleDriveTank(); + ~PxVehicleDriveTank(){} +//~serialization +}; +PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleDriveTank) & 15)); + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif //PX_VEHICLE_DRIVE_TANK_H diff --git a/sources/PhysX/PhysX/include/vehicle/PxVehicleNoDrive.h b/sources/PhysX/PhysX/include/vehicle/PxVehicleNoDrive.h new file mode 100644 index 00000000..69982da2 --- /dev/null +++ b/sources/PhysX/PhysX/include/vehicle/PxVehicleNoDrive.h @@ -0,0 +1,216 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_VEHICLE_NO_DRIVE_H +#define PX_VEHICLE_NO_DRIVE_H +/** \addtogroup vehicle + @{ +*/ + +#include "vehicle/PxVehicleWheels.h" +#include "vehicle/PxVehicleComponents.h" + + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +struct PxFilterData; +class PxGeometry; +class PxPhysics; +class PxVehicleDrivableSurfaceToTireFrictionPairs; +class PxShape; +class PxMaterial; +class PxRigidDynamic; + +/** +\brief Data structure with instanced dynamics data and configuration data of a vehicle with no drive model. +*/ +class PxVehicleNoDrive : public PxVehicleWheels +{ +//= ATTENTION! ===================================================================================== +// Changing the data layout of this class breaks the binary serialization format. See comments for +// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData +// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION +// accordingly. +//================================================================================================== +public: + + friend class PxVehicleUpdate; + + /** + \brief Allocate a PxVehicleNoDrive instance for a vehicle without drive model and with nbWheels + + \param[in] nbWheels is the number of wheels on the vehicle. + + \return The instantiated vehicle. + + @see free, setup + */ + static PxVehicleNoDrive* allocate(const PxU32 nbWheels); + + /** + \brief Deallocate a PxVehicleNoDrive instance. + @see allocate + */ + void free(); + + /** + \brief Set up a vehicle using simulation data for the wheels. + \param[in] physics is a PxPhysics instance that is needed to create special vehicle constraints that are maintained by the vehicle. + \param[in] vehActor is a PxRigidDynamic instance that is used to represent the vehicle in the PhysX SDK. + \param[in] wheelsData describes the configuration of all suspension/tires/wheels of the vehicle. The vehicle instance takes a copy of this data. + \note It is assumed that the first shapes of the actor are the wheel shapes, followed by the chassis shapes. To break this assumption use PxVehicleWheels::setWheelShapeMapping. + @see allocate, free, setToRestState, PxVehicleWheels::setWheelShapeMapping + */ + void setup + (PxPhysics* physics, PxRigidDynamic* vehActor, const PxVehicleWheelsSimData& wheelsData); + + /** + \brief Allocate and set up a vehicle using simulation data for the wheels. + \param[in] physics is a PxPhysics instance that is needed to create special vehicle constraints that are maintained by the vehicle. + \param[in] vehActor is a PxRigidDynamic instance that is used to represent the vehicle in the PhysX SDK. + \param[in] wheelsData describes the configuration of all suspension/tires/wheels of the vehicle. The vehicle instance takes a copy of this data. + \note It is assumed that the first shapes of the actor are the wheel shapes, followed by the chassis shapes. To break this assumption use PxVehicleWheels::setWheelShapeMapping. + \return The instantiated vehicle. + @see allocate, free, setToRestState, PxVehicleWheels::setWheelShapeMapping + */ + static PxVehicleNoDrive* create + (PxPhysics* physics, PxRigidDynamic* vehActor, const PxVehicleWheelsSimData& wheelsData); + + /** + \brief Set a vehicle to its rest state. Aside from the rigid body transform, this will set the vehicle and rigid body + to the state they were in immediately after setup or create. + \note Calling setToRestState invalidates the cached raycast hit planes under each wheel meaning that suspension line + raycasts need to be performed at least once with PxVehicleSuspensionRaycasts before calling PxVehicleUpdates. + @see setup, create, PxVehicleSuspensionRaycasts, PxVehicleUpdates + */ + void setToRestState(); + + /** + \brief Set the brake torque to be applied to a specific wheel + + \note The applied brakeTorque persists until the next call to setBrakeTorque + + \note The brake torque is specified in Newton metres. + + \param[in] id is the wheel being given the brake torque + \param[in] brakeTorque is the value of the brake torque + */ + void setBrakeTorque(const PxU32 id, const PxReal brakeTorque); + + /** + \brief Set the drive torque to be applied to a specific wheel + + \note The applied driveTorque persists until the next call to setDriveTorque + + \note The brake torque is specified in Newton metres. + + \param[in] id is the wheel being given the brake torque + \param[in] driveTorque is the value of the brake torque + */ + void setDriveTorque(const PxU32 id, const PxReal driveTorque); + + /** + \brief Set the steer angle to be applied to a specific wheel + + \note The applied steerAngle persists until the next call to setSteerAngle + + \note The steer angle is specified in radians. + + \param[in] id is the wheel being given the steer angle + \param[in] steerAngle is the value of the steer angle in radians. + */ + void setSteerAngle(const PxU32 id, const PxReal steerAngle); + + /** + \brief Get the brake torque that has been applied to a specific wheel + \param[in] id is the wheel being queried for its brake torque + \return The brake torque applied to the queried wheel. + */ + PxReal getBrakeTorque(const PxU32 id) const; + + /** + \brief Get the drive torque that has been applied to a specific wheel + \param[in] id is the wheel being queried for its drive torque + \return The drive torque applied to the queried wheel. + */ + PxReal getDriveTorque(const PxU32 id) const; + + /** + \brief Get the steer angle that has been applied to a specific wheel + \param[in] id is the wheel being queried for its steer angle + \return The steer angle (in radians) applied to the queried wheel. + */ + PxReal getSteerAngle(const PxU32 id) const; + +private: + + PxReal* mSteerAngles; + PxReal* mDriveTorques; + PxReal* mBrakeTorques; + +#if PX_P64_FAMILY + PxU32 mPad[2]; +#else + PxU32 mPad[1]; +#endif + + /** + \brief Test if the instanced dynamics and configuration data has legal values. + */ + bool isValid() const; + + +//serialization +public: + PxVehicleNoDrive(PxBaseFlags baseFlags) : PxVehicleWheels(baseFlags) {} + virtual void exportExtraData(PxSerializationContext&); + void importExtraData(PxDeserializationContext&); + static PxVehicleNoDrive* createObject(PxU8*& address, PxDeserializationContext& context); + static void getBinaryMetaData(PxOutputStream& stream); + virtual const char* getConcreteTypeName() const { return "PxVehicleNoDrive"; } + virtual bool isKindOf(const char* name) const { return !::strcmp("PxVehicleNoDrive", name) || PxBase::isKindOf(name); } + PxU32 getNbSteerAngle() const { return mWheelsSimData.getNbWheels(); } + PxU32 getNbDriveTorque() const { return mWheelsSimData.getNbWheels(); } + PxU32 getNbBrakeTorque() const { return mWheelsSimData.getNbWheels(); } +protected: + PxVehicleNoDrive(); + ~PxVehicleNoDrive() {} +//~serialization +}; +PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleNoDrive) & 15)); + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif //PX_VEHICLE_NO_DRIVE_H diff --git a/sources/PhysX/PhysX/include/vehicle/PxVehicleSDK.h b/sources/PhysX/PhysX/include/vehicle/PxVehicleSDK.h new file mode 100644 index 00000000..d47aa543 --- /dev/null +++ b/sources/PhysX/PhysX/include/vehicle/PxVehicleSDK.h @@ -0,0 +1,237 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_VEHICLE_SDK_H +#define PX_VEHICLE_SDK_H +/** \addtogroup vehicle + @{ +*/ + +#include "foundation/Px.h" +#include "common/PxTypeInfo.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxPhysics; +class PxSerializationRegistry; + +/** +\brief Initialize the PhysXVehicle library. + +Call this before using any of the vehicle functions. + +\param physics The PxPhysics instance. +\param serializationRegistry PxSerializationRegistry instance, if NULL vehicle serialization is not supported. + +\note This function must be called after PxFoundation and PxPhysics instances have been created. +\note If a PxSerializationRegistry instance is specified then PhysXVehicle is also dependent on PhysXExtensions. + +@see PxCloseVehicleSDK +*/ +PX_C_EXPORT bool PX_CALL_CONV PxInitVehicleSDK(PxPhysics& physics, PxSerializationRegistry* serializationRegistry = NULL); + + +/** +\brief Shut down the PhysXVehicle library. + +Call this function as part of the physx shutdown process. + +\param serializationRegistry PxSerializationRegistry instance, if non-NULL must be the same as passed into PxInitVehicleSDK. + +\note This function must be called prior to shutdown of PxFoundation and PxPhysics. +\note If the PxSerializationRegistry instance is specified this function must additionally be called prior to shutdown of PhysXExtensions. + +@see PxInitVehicleSDK +*/ +PX_C_EXPORT void PX_CALL_CONV PxCloseVehicleSDK(PxSerializationRegistry* serializationRegistry = NULL); + + +/** +\brief This number is the maximum number of wheels allowed for a vehicle. +*/ +#define PX_MAX_NB_WHEELS (20) + + +/** +\brief Compiler setting to enable recording of telemetry data + +@see PxVehicleUpdateSingleVehicleAndStoreTelemetryData, PxVehicleTelemetryData +*/ +#define PX_DEBUG_VEHICLE_ON (1) + + +/** +@see PxVehicleDrive4W, PxVehicleDriveTank, PxVehicleDriveNW, PxVehicleNoDrive, PxVehicleWheels::getVehicleType +*/ +struct PxVehicleTypes +{ + enum Enum + { + eDRIVE4W=0, + eDRIVENW, + eDRIVETANK, + eNODRIVE, + eUSER1, + eUSER2, + eUSER3, + eMAX_NB_VEHICLE_TYPES + }; +}; + + +/** +\brief An enumeration of concrete vehicle classes inheriting from PxBase. +\note This enum can be used to identify a vehicle object stored in a PxCollection. +@see PxBase, PxTypeInfo, PxBase::getConcreteType +*/ +struct PxVehicleConcreteType +{ + enum Enum + { + eVehicleNoDrive = PxConcreteType::eFIRST_VEHICLE_EXTENSION, + eVehicleDrive4W, + eVehicleDriveNW, + eVehicleDriveTank + }; +}; + + +/** +\brief Set the basis vectors of the vehicle simulation + +Default values PxVec3(0,1,0), PxVec3(0,0,1) + +Call this function before using PxVehicleUpdates unless the default values are correct. +*/ +void PxVehicleSetBasisVectors(const PxVec3& up, const PxVec3& forward); + + +/** +@see PxVehicleSetUpdateMode +*/ +struct PxVehicleUpdateMode +{ + enum Enum + { + eVELOCITY_CHANGE, + eACCELERATION + }; +}; + + +/** +\brief Set the effect of PxVehicleUpdates to be either to modify each vehicle's rigid body actor + +with an acceleration to be applied in the next PhysX SDK update or as an immediate velocity modification. + +Default behavior is immediate velocity modification. + +Call this function before using PxVehicleUpdates for the first time if the default is not the desired behavior. + +@see PxVehicleUpdates +*/ +void PxVehicleSetUpdateMode(PxVehicleUpdateMode::Enum vehicleUpdateMode); + +/** + +\brief Set threshold angles that are used to determine if a wheel hit is to be resolved by vehicle suspension or by rigid body collision. + + +\note ^ + N ___ + |** + ** + ** + %%% %%% ** + %%% %%% ** / + / + %%% %%% / + / + %%% %%% / + C / + %%% | ** %%% / + | ** / + %%% | **%%%/ + | X** + %%% | %%% / **_| ^ + | / D + %%% | %%% / + | / + | / + | / + | + ^ | + S \|/ + +The diagram above depicts a wheel centered at "C" that has hit an inclined plane at point "X". +The inclined plane has unit normal "N", while the suspension direction has unit vector "S". +The unit vector from the wheel center to the hit point is "D". +Hit points are analyzed by comparing the unit vectors D and N with the suspension direction S. +This analysis is performed in the contact modification callback PxVehicleModifyWheelContacts (when enabled) and in +PxVehicleUpdates (when non-blocking sweeps are enabled). +If the angle between D and S is less than pointRejectAngle the hit is accepted by the suspension in PxVehicleUpdates and rejected +by the contact modification callback PxVehicleModifyWheelContacts. +If the angle between -N and S is less than normalRejectAngle the hit is accepted by the suspension in PxVehicleUpdates and rejected +by the contact modification callback PxVehicleModifyWheelContacts. + +\param pointRejectAngle is the threshold angle used when comparing the angle between D and S. + +\param normalRejectAngle is the threshold angle used when comparing the angle between -N and S. + +\note PxVehicleUpdates ignores the rejection angles for raycasts and for sweeps that return blocking hits. + +\note Both angles have default values of Pi/4. + +@see PxVehicleSuspensionSweeps, PxVehicleModifyWheelContacts +*/ +void PxVehicleSetSweepHitRejectionAngles(const PxF32 pointRejectAngle, const PxF32 normalRejectAngle); + + +/** +\brief Determine the maximum acceleration experienced by PxRigidDynamic instances that are found to be in contact +with a wheel. + +\note Newton's Third Law states that every force has an equal and opposite force. As a consequence, forces applied to +the suspension must be applied to dynamic objects that lie under the wheel. This can lead to instabilities, particularly +when a heavy wheel is driving on a light object. The value of maxHitActorAcceleration clamps the applied force so that it never +generates an acceleration greater than the specified value. + +\note Default value of maxHitActorAcceleration is PX_MAX_REAL +*/ +void PxVehicleSetMaxHitActorAcceleration(const PxF32 maxHitActorAcceleration); + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif //PX_VEHICLE_SDK_H diff --git a/sources/PhysX/PhysX/include/vehicle/PxVehicleShaders.h b/sources/PhysX/PhysX/include/vehicle/PxVehicleShaders.h new file mode 100644 index 00000000..18d92440 --- /dev/null +++ b/sources/PhysX/PhysX/include/vehicle/PxVehicleShaders.h @@ -0,0 +1,79 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_VEHICLE_SHADERS_H +#define PX_VEHICLE_SHADERS_H +/** \addtogroup vehicle + @{ +*/ + +#include "foundation/PxSimpleTypes.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief Prototype of shader function that is used to compute wheel torque and tire forces. +\param[in] shaderData is the shader data for the tire being processed. The shader data describes the tire data in the format required by the tire model that is implemented by the shader function. +\param[in] tireFriction is the value of friction for the contact between the tire and the ground. +\param[in] longSlip is the value of longitudinal slip experienced by the tire. +\param[in] latSlip is the value of lateral slip experienced by the tire. +\param[in] camber is the camber angle of the tire in radians. +\param[in] wheelOmega is the rotational speed of the wheel. +\param[in] wheelRadius is the distance from the tire surface to the center of the wheel. +\param[in] recipWheelRadius is the reciprocal of wheelRadius. +\param[in] restTireLoad is the load force experienced by the tire when the vehicle is at rest. +\param[in] normalisedTireLoad is a pre-computed value equal to the load force on the tire divided by restTireLoad. +\param[in] tireLoad is the load force currently experienced by the tire (= restTireLoad*normalisedTireLoad) +\param[in] gravity is the magnitude of gravitational acceleration. +\param[in] recipGravity is the reciprocal of the magnitude of gravitational acceleration. +\param[out] wheelTorque is the torque that is to be applied to the wheel around the wheel's axle. +\param[out] tireLongForceMag is the magnitude of the longitudinal tire force to be applied to the vehicle's rigid body. +\param[out] tireLatForceMag is the magnitude of the lateral tire force to be applied to the vehicle's rigid body. +\param[out] tireAlignMoment is the aligning moment of the tire that is to be applied to the vehicle's rigid body (not currently used). +@see PxVehicleWheelsDynData::setTireForceShaderFunction, PxVehicleWheelsDynData::setTireForceShaderData +*/ +typedef void (*PxVehicleComputeTireForce) +(const void* shaderData, + const PxF32 tireFriction, + const PxF32 longSlip, const PxF32 latSlip, const PxF32 camber, + const PxF32 wheelOmega, const PxF32 wheelRadius, const PxF32 recipWheelRadius, + const PxF32 restTireLoad, const PxF32 normalisedTireLoad, const PxF32 tireLoad, + const PxF32 gravity, const PxF32 recipGravity, + PxF32& wheelTorque, PxF32& tireLongForceMag, PxF32& tireLatForceMag, PxF32& tireAlignMoment); + + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif //PX_VEHICLE_SHADERS_H diff --git a/sources/PhysX/PhysX/include/vehicle/PxVehicleTireFriction.h b/sources/PhysX/PhysX/include/vehicle/PxVehicleTireFriction.h new file mode 100644 index 00000000..cdc8ca75 --- /dev/null +++ b/sources/PhysX/PhysX/include/vehicle/PxVehicleTireFriction.h @@ -0,0 +1,223 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_VEHICLE_TIREFRICTION_H +#define PX_VEHICLE_TIREFRICTION_H +/** \addtogroup vehicle + @{ +*/ + +#include "foundation/PxSimpleTypes.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxMaterial; + +/** +\brief Driving surface type. Each PxMaterial is associated with a corresponding PxVehicleDrivableSurfaceType. +@see PxMaterial, PxVehicleDrivableSurfaceToTireFrictionPairs +*/ +struct PxVehicleDrivableSurfaceType +{ + enum + { + eSURFACE_TYPE_UNKNOWN=0xffffffff + }; + PxU32 mType; +}; + +/** +\brief Friction for each combination of driving surface type and tire type. +@see PxVehicleDrivableSurfaceType, PxVehicleTireData::mType +*/ +class PxVehicleDrivableSurfaceToTireFrictionPairs +{ +public: + + friend class VehicleSurfaceTypeHashTable; + + enum + { + eMAX_NB_SURFACE_TYPES=256 + }; + + /** + \brief Allocate the memory for a PxVehicleDrivableSurfaceToTireFrictionPairs instance + that can hold data for combinations of tire type and surface type with up to maxNbTireTypes types of tire and maxNbSurfaceTypes types of surface. + + \param[in] maxNbTireTypes is the maximum number of allowed tire types. + \param[in] maxNbSurfaceTypes is the maximum number of allowed surface types. Must be less than or equal to eMAX_NB_SURFACE_TYPES + + \return a PxVehicleDrivableSurfaceToTireFrictionPairs instance that can be reused later with new type and friction data. + + @see setup + */ + static PxVehicleDrivableSurfaceToTireFrictionPairs* allocate + (const PxU32 maxNbTireTypes, const PxU32 maxNbSurfaceTypes); + + /** + \brief Set up a PxVehicleDrivableSurfaceToTireFrictionPairs instance for combinations of nbTireTypes tire types and nbSurfaceTypes surface types. + + \param[in] nbTireTypes is the number of different types of tire. This value must be less than or equal to maxNbTireTypes specified in allocate(). + \param[in] nbSurfaceTypes is the number of different types of surface. This value must be less than or equal to maxNbSurfaceTypes specified in allocate(). + \param[in] drivableSurfaceMaterials is an array of PxMaterial pointers of length nbSurfaceTypes. + \param[in] drivableSurfaceTypes is an array of PxVehicleDrivableSurfaceType instances of length nbSurfaceTypes. + + \note If the pointer to the PxMaterial that touches the tire is found in drivableSurfaceMaterials[x] then the surface type is drivableSurfaceTypes[x].mType + and the friction is the value that is set with setTypePairFriction(drivableSurfaceTypes[x].mType, PxVehicleTireData::mType, frictionValue). + + \note A friction value of 1.0 will be assigned as default to each combination of tire and surface type. To override this use setTypePairFriction. + @see release, setTypePairFriction, getTypePairFriction, PxVehicleTireData.mType + */ + void setup + (const PxU32 nbTireTypes, const PxU32 nbSurfaceTypes, + const PxMaterial** drivableSurfaceMaterials, const PxVehicleDrivableSurfaceType* drivableSurfaceTypes); + + /** + \brief Deallocate a PxVehicleDrivableSurfaceToTireFrictionPairs instance + */ + void release(); + + /** + \brief Set the friction for a specified pair of tire type and drivable surface type. + + \param[in] surfaceType describes the surface type + \param[in] tireType describes the tire type. + \param[in] value describes the friction coefficient for the combination of surface type and tire type. + */ + void setTypePairFriction(const PxU32 surfaceType, const PxU32 tireType, const PxReal value); + + /** + \brief Return the friction for a specified combination of surface type and tire type. + \return The friction for a specified combination of surface type and tire type. + \note The final friction value used by the tire model is the value returned by getTypePairFriction + multiplied by the value computed from PxVehicleTireData::mFrictionVsSlipGraph + @see PxVehicleTireData::mFrictionVsSlipGraph + */ + PxReal getTypePairFriction(const PxU32 surfaceType, const PxU32 tireType) const; + + /** + \brief Return the maximum number of surface types + \return The maximum number of surface types + @see allocate + */ + PxU32 getMaxNbSurfaceTypes() const {return mMaxNbSurfaceTypes;} + + /** + \brief Return the maximum number of tire types + \return The maximum number of tire types + @see allocate + */ + PxU32 getMaxNbTireTypes() const {return mMaxNbTireTypes;} + +private: + + /** + \brief Ptr to base address of a 2d PxReal array with dimensions [mNbSurfaceTypes][mNbTireTypes] + + \note Each element of the array describes the maximum friction provided by a surface type-tire type combination. + eg the friction corresponding to a combination of surface type x and tire type y is mPairs[x][y] + */ + PxReal* mPairs; + + /** + \brief Ptr to 1d array of material ptrs that is of length mNbSurfaceTypes. + + \note If the PxMaterial that touches the tire corresponds to mDrivableSurfaceMaterials[x] then the drivable surface + type is mDrivableSurfaceTypes[x].mType and the friction for that contact is mPairs[mDrivableSurfaceTypes[x].mType][y], + assuming a tire type y. + + \note If the PxMaterial that touches the tire is not found in mDrivableSurfaceMaterials then the friction is + mPairs[0][y], assuming a tire type y. + */ + const PxMaterial** mDrivableSurfaceMaterials; + + /** + \brief Ptr to 1d array of PxVehicleDrivableSurfaceType that is of length mNbSurfaceTypes. + + \note If the PxMaterial that touches the tire is found in mDrivableSurfaceMaterials[x] then the drivable surface + type is mDrivableSurfaceTypes[x].mType and the friction for that contact is mPairs[mDrivableSurfaceTypes[x].mType][y], + assuming a tire type y. + + \note If the PxMaterial that touches the tire is not found in mDrivableSurfaceMaterials then the friction is + mPairs[0][y], assuming a tire type y. + */ + PxVehicleDrivableSurfaceType* mDrivableSurfaceTypes; + + /** + \brief Number of different driving surface types. + + \note mDrivableSurfaceMaterials and mDrivableSurfaceTypes are both 1d arrays of length mMaxNbSurfaceTypes. + + \note mNbSurfaceTypes must be less than or equal to mMaxNbSurfaceTypes. + */ + PxU32 mNbSurfaceTypes; + + /** + \brief Maximum number of different driving surface types. + + \note mMaxNbSurfaceTypes must be less than or equal to eMAX_NB_SURFACE_TYPES. + */ + PxU32 mMaxNbSurfaceTypes; + + /** + \brief Number of different tire types. + + \note Tire types stored in PxVehicleTireData.mType + */ + PxU32 mNbTireTypes; + + /** + \brief Maximum number of different tire types. + + \note Tire types stored in PxVehicleTireData.mType + */ + PxU32 mMaxNbTireTypes; + + +#if !PX_P64_FAMILY + PxU32 mPad[1]; +#else + PxU32 mPad[2]; +#endif + + PxVehicleDrivableSurfaceToTireFrictionPairs(){} + ~PxVehicleDrivableSurfaceToTireFrictionPairs(){} +}; +PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleDrivableSurfaceToTireFrictionPairs) & 15)); + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif //PX_VEHICLE_TIREFRICTION_H diff --git a/sources/PhysX/PhysX/include/vehicle/PxVehicleUpdate.h b/sources/PhysX/PhysX/include/vehicle/PxVehicleUpdate.h new file mode 100644 index 00000000..40306fdc --- /dev/null +++ b/sources/PhysX/PhysX/include/vehicle/PxVehicleUpdate.h @@ -0,0 +1,581 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_VEHICLE_UPDATE_H +#define PX_VEHICLE_UPDATE_H +/** \addtogroup vehicle + @{ +*/ + +#include "vehicle/PxVehicleSDK.h" +#include "vehicle/PxVehicleTireFriction.h" +#include "foundation/PxSimpleTypes.h" +#include "foundation/PxMemory.h" +#include "foundation/PxTransform.h" +#include "PxBatchQueryDesc.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + + class PxBatchQuery; + class PxContactModifyPair; + class PxVehicleWheels; + class PxVehicleDrivableSurfaceToTireFrictionPairs; + class PxVehicleTelemetryData; + + /** + \brief Structure containing data describing the non-persistent state of each suspension/wheel/tire unit. + This structure is filled out in PxVehicleUpdates and PxVehicleUpdateSingleVehicleAndStoreTelemetryData + @see PxVehicleUpdates, PxVehicleUpdateSingleVehicleAndStoreTelemetryData + */ + struct PxWheelQueryResult + { + PxWheelQueryResult() + { + PxMemZero(this, sizeof(PxWheelQueryResult)); + isInAir=true; + tireSurfaceType = PxU32(PxVehicleDrivableSurfaceType::eSURFACE_TYPE_UNKNOWN); + localPose = PxTransform(PxIdentity); + } + + /** + \brief Start point of suspension line raycast/sweep used in the raycast/sweep completed immediately before PxVehicleUpdates. + \note If no raycast/sweep for the corresponding suspension was performed immediately prior to PxVehicleUpdates then (0,0,0) is stored. + @see PxVehicleSuspensionRaycasts, PxVehicleSuspensionRaycasts + */ + PxVec3 suspLineStart; + + /** + \brief Directions of suspension line raycast/sweep used in the raycast/sweep completed immediately before PxVehicleUpdates. + \note If no raycast/sweep for the corresponding suspension was performed immediately prior to PxVehicleUpdates then (0,0,0) is stored. + @see PxVehicleSuspensionRaycasts, PxVehicleSuspensionRaycasts + */ + PxVec3 suspLineDir; + + /** + \brief Lengths of suspension line raycast/sweep used in raycast/sweep completed immediately before PxVehicleUpdates. + \note If no raycast/sweep for the corresponding suspension was performed immediately prior to PxVehicleUpdates then 0 is stored. + @see PxVehicleSuspensionRaycasts, PxVehicleSuspensionRaycasts + */ + PxReal suspLineLength; + + /** + \brief If suspension travel limits forbid the wheel from touching the drivable surface then isInAir is true. + \note If the wheel can be placed on the contact plane of the most recent suspension line raycast/sweep then isInAir is false. + \note If #PxVehicleWheelsSimFlag::eLIMIT_SUSPENSION_EXPANSION_VELOCITY is set, then isInAir will also be true if the suspension + force is not large enough to expand to the target length in the given simulation time step. + \note If no raycast/sweep for the corresponding suspension was performed immediately prior to PxVehicleUpdates then isInAir + is computed using the contact plane that was hit by the most recent suspension line raycast/sweep. + */ + bool isInAir; + + /** + \brief PxActor instance of the driving surface under the corresponding vehicle wheel. + \note If suspension travel limits forbid the wheel from touching the drivable surface then tireContactActor is NULL. + \note If no raycast/sweep for the corresponding suspension was performed immediately prior to PxVehicleUpdates then NULL is stored. + */ + PxActor* tireContactActor; + + /** + \brief PxShape instance of the driving surface under the corresponding vehicle wheel. + \note If suspension travel limits forbid the wheel from touching the drivable surface then tireContactShape is NULL. + \note If no raycast/sweep for the corresponding suspension was performed immediately prior to PxVehicleUpdates then NULL is stored. + */ + PxShape* tireContactShape; + + /** + \brief PxMaterial instance of the driving surface under the corresponding vehicle wheel. + \note If suspension travel limits forbid the wheel from touching the drivable surface then tireSurfaceMaterial is NULL. + \note If no raycast/sweep for the corresponding suspension was performed immediately prior to PxVehicleUpdates then NULL is stored. + */ + const PxMaterial* tireSurfaceMaterial; + + /** + \brief Surface type integer that corresponds to the mapping between tireSurfaceMaterial and integer as + described in PxVehicleDrivableSurfaceToTireFrictionPairs. + \note If suspension travel limits forbid the wheel from touching the drivable surface then tireSurfaceType is + PxVehicleDrivableSurfaceType::eSURFACE_TYPE_UNKNOWN. + \note If no raycast/sweep for the corresponding suspension was performed immediately prior to PxVehicleUpdates then + PxVehicleDrivableSurfaceType::eSURFACE_TYPE_UNKNOWN is stored. + @see PxVehicleDrivableSurfaceToTireFrictionPairs + */ + PxU32 tireSurfaceType; + + /** + \brief Point on the drivable surface hit by the most recent suspension raycast or sweep. + \note If suspension travel limits forbid the wheel from touching the drivable surface then the contact point is (0,0,0). + \note If no raycast or sweep for the corresponding suspension was performed immediately prior to PxVehicleUpdates then (0,0,0) is stored. + */ + PxVec3 tireContactPoint; + + /** + \brief Normal on the drivable surface at the hit point of the most recent suspension raycast or sweep. + \note If suspension travel limits forbid the wheel from touching the drivable surface then the contact normal is (0,0,0). + \note If no raycast or sweep for the corresponding suspension was performed immediately prior to PxVehicleUpdates then (0,0,0) is stored. + */ + PxVec3 tireContactNormal; + + /** + \brief Friction experienced by the tire for the combination of tire type and surface type after accounting + for the friction vs slip graph. + \note If suspension travel limits forbid the wheel from touching the drivable surface then the tire friction is 0. + \note If no raycast or sweep for the corresponding suspension was performed immediately prior to PxVehicleUpdates then the + stored tire friction is the value computed in PxVehicleUpdates that immediately followed the last raycast or sweep. + @see PxVehicleDrivableSurfaceToTireFrictionPairs, PxVehicleTireData + */ + PxReal tireFriction; + + /** + \brief Compression of the suspension spring. + \note If suspension travel limits forbid the wheel from touching the drivable surface then the jounce is -PxVehicleSuspensionData.mMaxDroop + The jounce can never exceed PxVehicleSuspensionData.mMaxCompression. Positive values result when the suspension is compressed from + the rest position, while negative values mean the suspension is elongated from the rest position. + \note If no raycast or sweep for the corresponding suspension was performed immediately prior to PxVehicleUpdates then the + suspension compression is computed using the contact plane that was hit by the most recent suspension line raycast or sweep. + */ + PxReal suspJounce; + + /** + \brief Magnitude of force applied by the suspension spring along the direction of suspension travel. + \note If suspension travel limits forbid the wheel from touching the drivable surface then the force is 0 + \note If no raycast or sweep for the corresponding suspension was performed immediately prior to PxVehicleUpdates then the + suspension spring force is computed using the contact plane that was hit by the most recent suspension line raycast or sweep. + @see PxVehicleWheelsSimData::getSuspTravelDirection + */ + PxReal suspSpringForce; + + /** + \brief Forward direction of the wheel/tire accounting for steer/toe/camber angle projected on to the contact plane of the drivable surface. + \note If suspension travel limits forbid the wheel from touching the drivable surface then tireLongitudinalDir is (0,0,0) + \note If no raycast or sweep for the corresponding suspension was performed immediately prior to PxVehicleUpdates then the + tire longitudinal direction is computed using the contact plane that was hit by the most recent suspension line raycast or sweep. + */ + PxVec3 tireLongitudinalDir; + + /** + \brief Lateral direction of the wheel/tire accounting for steer/toe/camber angle projected on to the contact plan of the drivable surface. + \note If suspension travel limits forbid the wheel from touching the drivable surface then tireLateralDir is (0,0,0) + \note If no raycast or sweep for the corresponding suspension was performed immediately prior to PxVehicleUpdates then the + tire lateral direction is computed using the contact plane that was hit by the most recent suspension line raycast or sweep. + */ + PxVec3 tireLateralDir; + + /** + \brief Longitudinal slip of the tire. + \note If suspension travel limits forbid the wheel from touching the drivable surface then longitudinalSlip is 0.0 + \note The longitudinal slip is approximately (w*r - vz) / PxAbs(vz) where w is the angular speed of the wheel, r is the radius of the wheel, and + vz component of rigid body velocity computed at the wheel base along the longitudinal direction of the tire. + \note If no raycast or sweep for the corresponding suspension was performed immediately prior to PxVehicleUpdates then the + tire longitudinal slip is computed using the contact plane that was hit by the most recent suspension line raycast or sweep. + */ + PxReal longitudinalSlip; + + /** + \brief Lateral slip of the tire. + \note If suspension travel limits forbid the wheel from touching the drivable surface then lateralSlip is 0.0 + \note The lateral slip angle is approximately PxAtan(vx / PxAbs(vz)) where vx and vz are the components of rigid body velocity at the wheel base + along the wheel's lateral and longitudinal directions, respectively. + \note If no raycast or sweep for the corresponding suspension was performed immediately prior to PxVehicleUpdates then the + tire lateral slip is computed using the contact plane that was hit by the most recent suspension line raycast or sweep. + */ + PxReal lateralSlip; + + /** + \brief Steer angle of the wheel about the "up" vector accounting for input steer and toe and, if applicable, Ackermann steer correction. + @see PxVehicleWheelData::mToeAngle + */ + PxReal steerAngle; + + /** + \brief Local pose of the wheel. + */ + PxTransform localPose; + }; + + struct PxVehicleWheelQueryResult + { + /** + \brief Pointer to an PxWheelQueryResult buffer of length nbWheelQueryResults + The wheelQueryResults buffer must persist until the end of PxVehicleUpdates + A NULL pointer is permitted. + The wheelQueryResults buffer is left unmodified in PxVehicleUpdates for vehicles with sleeping rigid bodies + whose control inputs indicate they should remain inert. + @see PxVehicleUpdates + */ + PxWheelQueryResult* wheelQueryResults; + + /** + \brief The length of the wheelQueryResults buffer. This value corresponds to the + number of wheels in the associated vehicle in PxVehicleUpdates. + */ + PxU32 nbWheelQueryResults; + }; + + /** + \brief Structure containing data that is computed for a wheel during concurrent calls to PxVehicleUpdates + but which cannot be safely concurrently applied. + + @see PxVehicleUpdates, PxVehiclePostUpdates, PxVehicleConcurrentUpdate + */ + struct PxVehicleWheelConcurrentUpdateData + { + friend class PxVehicleUpdate; + + PxVehicleWheelConcurrentUpdateData() + : localPose(PxTransform(PxIdentity)), + hitActor(NULL), + hitActorForce(PxVec3(0,0,0)), + hitActorForcePosition(PxVec3(0,0,0)) + { + } + + private: + + PxTransform localPose; + PxRigidDynamic* hitActor; + PxVec3 hitActorForce; + PxVec3 hitActorForcePosition; + }; + + /** + \brief Structure containing data that is computed for a vehicle and its wheels during concurrent calls to PxVehicleUpdates + but which cannot be safely concurrently applied. + + @see PxVehicleUpdates, PxVehiclePostUpdates, PxVehicleWheelConcurrentUpdateData + */ + + struct PxVehicleConcurrentUpdateData + { + friend class PxVehicleUpdate; + + PxVehicleConcurrentUpdateData() + : concurrentWheelUpdates(NULL), + nbConcurrentWheelUpdates(0), + linearMomentumChange(PxVec3(0,0,0)), + angularMomentumChange(PxVec3(0,0,0)), + staySleeping(false), + wakeup(false) + { + } + + /** + \brief Pointer to an PxVehicleWheelConcurrentUpdate buffer of length nbConcurrentWheelUpdates + The concurrentWheelUpdates buffer must persist until the end of PxVehiclePostUpdates + A NULL pointer is not permitted. + @see PxVehicleUpdates, PxVehiclePostUpdates + */ + PxVehicleWheelConcurrentUpdateData* concurrentWheelUpdates; + + /** + \brief The length of the concurrentWheelUpdates buffer. This value corresponds to the + number of wheels in the associated vehicle passed to PxVehicleUpdates. + */ + PxU32 nbConcurrentWheelUpdates; + + private: + + PxVec3 linearMomentumChange; + PxVec3 angularMomentumChange; + bool staySleeping; + bool wakeup; + }; + + /** + \brief Perform raycasts for all suspension lines for all vehicles. + + \param[in] batchQuery is a PxBatchQuery instance used to specify shader data and functions for the raycast scene queries. + + \param[in] nbVehicles is the number of vehicles in the vehicles array. + + \param[in] vehicles is an array of all vehicles that are to have a raycast issued from each wheel. + + \param[in] nbSceneQueryResults must be greater than or equal to the total number of wheels of all the vehicles in the vehicles array; that is, + sceneQueryResults must have dimensions large enough for one raycast hit result per wheel for all the vehicles in the vehicles array. + + \param[in] sceneQueryResults must persist without being overwritten until the end of the next PxVehicleUpdates call. + + \param[in] vehiclesToRaycast is an array of bools of length nbVehicles that is used to decide if raycasts will be performed for the corresponding vehicle + in the vehicles array. If vehiclesToRaycast[i] is true then suspension line raycasts will be performed for vehicles[i]. If vehiclesToRaycast[i] is + false then suspension line raycasts will not be performed for vehicles[i]. + + \note If vehiclesToRaycast is NULL then raycasts are performed for all vehicles in the vehicles array. + + \note If vehiclesToRaycast[i] is false then the vehicle stored in vehicles[i] will automatically use the raycast or sweep hit planes recorded by the most recent + suspension sweeps or raycasts for that vehicle. For vehicles far from the camera or not visible on the screen it can be + optimal to only perform suspension line raycasts every Nth update rather than every single update. The accuracy of the cached contact plane + naturally diminishes as N increase, meaning that wheels might start to hover or intersect the ground for large values of N or even with values close to 1 in + conjunction with large vehicle speeds and/or geometry that has low spatial coherence. + + \note Calling setToRestState invalidates any cached hit planes. Prior to calling PxVehicleUpdates each vehicle needs to perform suspension line raycasts + or sweeps at least once after instantiation and at least once after calling setToRestState. + + \note Each raycast casts along the suspension travel direction from the position of the top of the wheel at maximum suspension compression + to the position of the base of the wheel at maximum droop. Raycasts that start inside a PxShape are subsequently ignored by the + corresponding vehicle. + + \note Only blocking hits are supported (PxQueryHitType::eBLOCK). + + @see PxVehicleDrive4W::setToRestState, PxVehicleDriveNW::setToRestState, PxVehicleDriveTank::setToRestState, PxVehicleNoDrive::setToRestState + */ + void PxVehicleSuspensionRaycasts + (PxBatchQuery* batchQuery, + const PxU32 nbVehicles, PxVehicleWheels** vehicles, + const PxU32 nbSceneQueryResults, PxRaycastQueryResult* sceneQueryResults, + const bool* vehiclesToRaycast = NULL); + + + /** + \brief Perform sweeps for all suspension lines for all vehicles. + + \param[in] batchQuery is a PxBatchQuery instance used to specify shader data and functions for the sweep scene queries. + + \param[in] nbVehicles is the number of vehicles in the vehicles array. + + \param[in] vehicles is an array of all vehicles that are to have a sweep issued from each wheel. + + \param[in] nbSceneQueryResults must be greater than or equal to the total number of wheels of all the vehicles in the vehicles array; that is, + sceneQueryResults must have dimensions large enough for one sweep hit result per wheel for all the vehicles in the vehicles array. + + \param[in] sceneQueryResults must persist without being overwritten until the end of the next PxVehicleUpdates call. + + \param[in] nbHitsPerQuery is the maximum numbers of hits that will be returned for each query. + + \param[in] vehiclesToSweep is an array of bools of length nbVehicles that is used to decide if sweeps will be performed for the corresponding vehicle + in the vehicles array. If vehiclesToSweep[i] is true then suspension sweeps will be performed for vehicles[i]. If vehiclesToSweep[i] is + false then suspension sweeps will not be performed for vehicles[i]. + + \param[in] sweepWidthScale scales the geometry of the wheel used in the sweep. Values < 1 result in a thinner swept wheel, while values > 1 result in a fatter swept wheel. + + \param[in] sweepRadiusScale scales the geometry of the wheel used in the sweep. Values < 1 result in a larger swept wheel, while values > 1 result in a smaller swept wheel. + + \note If vehiclesToSweep is NULL then sweeps are performed for all vehicles in the vehicles array. + + \note If vehiclesToSweep[i] is false then the vehicle stored in vehicles[i] will automatically use the most recent sweep or raycast hit planes + recorded by the most recent suspension sweeps or raycasts for that vehicle. For vehicles far from the camera or not visible on the screen it can be + optimal to only perform suspension queries every Nth update rather than every single update. The accuracy of the cached contact plane + naturally diminishes as N increase, meaning that wheels might start to hover or intersect the ground for large values of N or even with values close to 1 in + conjunction with large vehicle speeds and/or geometry that has low spatial coherence. + + \note Calling setToRestState invalidates any cached hit planes. Prior to calling PxVehicleUpdates each vehicle needs to perform suspension raycasts + or sweeps at least once after instantiation and at least once after calling setToRestState. + + \note Each sweep casts the wheel's shape along the suspension travel direction from the position of the top of the wheel at maximum suspension compression + to the position of the base of the wheel at maximum droop. Sweeps that start inside a PxShape are subsequently ignored by the + corresponding vehicle. + + \note A scale can be applied to the shape so that a modified shape is swept through the scene. The parameters sweepWidthScale and sweepRadiusScale scale the + swept wheel shape in the width and radial directions. It is sometimes a good idea to sweep a thinner wheel to allow contact with other dynamic actors to be resolved + first before attempting to drive on them. + + \note Blocking hits (PxQueryHitType::eBLOCK) and non-blocking hits (PxQueryHitType::TOUCH) are supported. If the pre-and post-filter functions of the PxBatchQuery + instance are set up to return blocking hits it is recommended to set nbHitsPerQuery = 1. If the filter functions returns touch hits then it is recommended to + set nbHitsPerQuery > 1. The exact value depends on the expected complexity of the geometry that lies under the wheel. For complex geometry, especially with dynamic + objects, it is recommended to use non-blocking hits. The vehicle update function will analyze all returned hits and choose the most appropriate using the thresholds + set in PxVehicleSetSweepHitRejectionAngles. + + @see PxVehicleDrive4W::setToRestState, PxVehicleDriveNW::setToRestState, PxVehicleDriveTank::setToRestState, PxVehicleNoDrive::setToRestState + + @see PxBatchQuery::sweep + + @see PxVehicleSetSweepHitRejectionAngles + */ + void PxVehicleSuspensionSweeps + (PxBatchQuery* batchQuery, + const PxU32 nbVehicles, PxVehicleWheels** vehicles, + const PxU32 nbSceneQueryResults, PxSweepQueryResult* sceneQueryResults, const PxU16 nbHitsPerQuery, + const bool* vehiclesToSweep = NULL, + const PxF32 sweepWidthScale = 1.0f, const PxF32 sweepRadiusScale = 1.0f); + + /** + \brief A function called from PxContactModifyCallback::onContactModify. The function determines if rigid body contact points + recorded for the wheel's PxShape are likely to be duplicated and resolved by the wheel's suspension raycast. Contact points that will be + resolved by the suspension are ignored. Contact points that are accepted (rather than ignored) are modified to account for the effect of the + suspension geometry and the angular speed of the wheel. + + \param[in] vehicle is a reference to the PxVehicleWheels instance that owns the wheel + + \param[in] wheelId is the id of the wheel + + \param[in] wheelTangentVelocityMultiplier determines the amount of wheel angular velocity that is used to modify the target relative velocity of the contact. + The target relative velocity is modified by adding a vector equal to the tangent velocity of the rotating wheel at the contact point and scaled by + wheelTangentVelocityMultiplier. The value of wheelTangentVelocityMultiplier is limited to the range (0,1). Higher values mimic higher values of friction + and tire load, while lower values mimic lower values of friction and tire load. + + \param[in] maxImpulse determines the maximum impulse strength that the contacts can apply when a wheel is in contact with a PxRigidDynamic. This value is ignored for + contacts with PxRigidStatic instances. + + \param[in,out] contactModifyPair describes the set of contacts involving the PxShape of the specified wheel and one other shape. The contacts in the contact set are + ignored or modified as required. + + \note[in] Contact points are accepted or rejected using the threshold angles specified in the function PxVehicleSetSweepHitRejectionAngles. + + \note If a contact point is not rejected it is modified to account for the wheel rotation speed. + + \note Set maxImpulse to PX_MAX_F32 to allow any impulse value to be applied. + + \note Reduce maxImpulse if the wheels are frequently colliding with light objects with mass much less than the vehicle's mass. + Reducing this value encourages numerical stability. + + @see PxContactModifyCallback::onContactModify, PxVehicleSetSweepHitRejectionAngles + */ + PxU32 PxVehicleModifyWheelContacts + (const PxVehicleWheels& vehicle, const PxU32 wheelId, + const PxF32 wheelTangentVelocityMultiplier, const PxReal maxImpulse, + PxContactModifyPair& contactModifyPair); + + + /** + \brief Update an array of vehicles by either applying an acceleration to the rigid body actor associated with + each vehicle or by an immediate update of the velocity of the actor. + + \note The update mode (acceleration or velocity change) can be selected with PxVehicleSetUpdateMode. + + \param[in] timestep is the timestep of the update + + \param[in] gravity is the value of gravitational acceleration + + \param[in] vehicleDrivableSurfaceToTireFrictionPairs describes the mapping between each PxMaterial ptr and an integer representing a + surface type. It also stores the friction value for each combination of surface and tire type. + + \param[in] nbVehicles is the number of vehicles pointers in the vehicles array + + \param[in,out] vehicles is an array of length nbVehicles containing all vehicles to be updated by the specified timestep + + \param[out] vehicleWheelQueryResults is an array of length nbVehicles storing the wheel query results of each corresponding vehicle and wheel in the + vehicles array. A NULL pointer is permitted. + + \param[out] vehicleConcurrentUpdates is an array of length nbVehicles. It is only necessary to specify vehicleConcurrentUpdates if PxVehicleUpdates is + called concurrently. The element vehicleWheelQueryResults[i] of the array stores data that is computed for vehicle[i] during PxVehicleUpdates but which + cannot be safely written when concurrently called. The data computed and stored in vehicleConcurrentUpdates must be passed to PxVehiclePostUpdates, where + it is applied to all relevant actors in sequence. A NULL pointer is permitted. + + \note The vehicleWheelQueryResults buffer must persist until the end of PxVehicleUpdates. + + \note The vehicleWheelQueryResults buffer is left unmodified for vehicles with sleeping rigid bodies whose control inputs indicate they should remain inert. + + \note If PxVehicleUpdates is called concurrently then vehicleConcurrentUpdates must be specified. Do not specify vehicleConcurrentUpdates is PxVehicleUpdates + is not called concurrently. + + \note The vehicleConcurrentUpdates buffer must persist until the end of PxVehiclePostUpdate. + + \note If any vehicle has one or more disabled wheels (PxVehicleWheelsSimData::disableWheel) then the disabled wheels must not be associated + with a PxShape (PxVehicleWheelsSimData::setWheelShapeMapping); the differential of the vehicle must be configured so that no drive torque + is delivered to a disabled wheel; and the wheel must have zero rotation speed (PxVehicleWheelsDynData::setWheelRotationSpeed) + + \note PxVehicleUpdates may be called concurrently provided all concurrent calls to PxVehicleUpdates involve only vehicles in the scene specified by PxVehicleUpdateSetScene. + PxVehicleUpdates must never run concurrently with PxVehicleUpdateSingleVehicleAndStoreTelemetryData. + + @see PxVehicleSetUpdateMode, PxVehicleWheelsSimData::disableWheel, PxVehicleWheelsSimData::setWheelShapeMapping, PxVehicleWheelsDynData::setWheelRotationSpeed, + PxVehiclePostUpdates + */ + void PxVehicleUpdates( + const PxReal timestep, const PxVec3& gravity, + const PxVehicleDrivableSurfaceToTireFrictionPairs& vehicleDrivableSurfaceToTireFrictionPairs, + const PxU32 nbVehicles, PxVehicleWheels** vehicles, PxVehicleWheelQueryResult* vehicleWheelQueryResults, PxVehicleConcurrentUpdateData* vehicleConcurrentUpdates = NULL); + + + /** + \brief Apply actor changes that were computed in concurrent calls to PxVehicleUpdates but which could not be safely applied due to the concurrency. + + \param[in] vehicleConcurrentUpdates is an array of length nbVehicles where vehicleConcurrentUpdates[i] contains data describing actor changes that + were computed for vehicles[i] during concurrent calls to PxVehicleUpdates. + + \param[in] nbVehicles is the number of vehicles pointers in the vehicles array + + \param[in,out] vehicles is an array of length nbVehicles containing all vehicles that were partially updated in concurrent calls to PxVehicleUpdates. + + @see PxVehicleUpdates + */ + void PxVehiclePostUpdates( + const PxVehicleConcurrentUpdateData* vehicleConcurrentUpdates, const PxU32 nbVehicles, PxVehicleWheels** vehicles); + + + /** + \brief Shift the origin of vehicles by the specified vector. + + Call this method to adjust the internal data structures of vehicles to reflect the shifted origin location + (the shift vector will get subtracted from all world space spatial data). + + \note It is the user's responsibility to keep track of the summed total origin shift and adjust all input/output to/from PhysXVehicle accordingly. + + \note This call will not automatically shift the PhysX scene and its objects. You need to call PxScene::shiftOrigin() seperately to keep the systems in sync. + + \param[in] shift is the translation vector to shift the origin by. + + \param[in] nbVehicles is the number of vehicles in the vehicles array. + + \param[in,out] vehicles is an array of all vehicles that should be updated to map to the new scene origin. + */ + void PxVehicleShiftOrigin(const PxVec3& shift, const PxU32 nbVehicles, PxVehicleWheels** vehicles); + +#if PX_DEBUG_VEHICLE_ON + /** + \brief Update an single vehicle by either applying an acceleration to the rigid body actor associated with + each vehicle or by an immediate update of the velocity of the actor. Also record telemetry data from the + vehicle so that it may be visualized or queried. + + \note The update mode (acceleration or velocity change) can be selected with PxVehicleSetUpdateMode. + + \param[in] timestep is the timestep of the update + + \param[in] gravity is the value of gravitational acceleration + + \param[in] vehicleDrivableSurfaceToTireFrictionPairs describes the mapping between each PxMaterial ptr and an integer representing a + surface type. It also stores the friction value for each combination of surface and tire type. + + \param[in,out] focusVehicle is the vehicle to be updated and have its telemetry data recorded + + \param[out] vehicleWheelQueryResults is an array of length 1 storing the wheel query results of each wheel of the vehicle/ + A NULL pointer is permitted. + + \param[out] telemetryData is the data structure used to record telemetry data during the update for later query or visualization + + \note The vehicleWheelQueryResults buffer must persist until the end of PxVehicleUpdates + + \note The vehicleWheelQueryResults buffer is left unmodified for vehicles with sleeping rigid bodies whose control inputs indicate they should remain inert. + + \note PxVehicleUpdateSingleVehicleAndStoreTelemetryData is not thread-safe. As a consequence, it must run sequentially and never concurrently with PxVehicleUpdates + + @see PxVehicleSetUpdateMode, PxVehicleTelemetryData + */ + void PxVehicleUpdateSingleVehicleAndStoreTelemetryData + (const PxReal timestep, const PxVec3& gravity, + const PxVehicleDrivableSurfaceToTireFrictionPairs& vehicleDrivableSurfaceToTireFrictionPairs, + PxVehicleWheels* focusVehicle, PxVehicleWheelQueryResult* vehicleWheelQueryResults, + PxVehicleTelemetryData& telemetryData); +#endif + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif //PX_VEHICLE_UPDATE_H diff --git a/sources/PhysX/PhysX/include/vehicle/PxVehicleUtil.h b/sources/PhysX/PhysX/include/vehicle/PxVehicleUtil.h new file mode 100644 index 00000000..b2bfd2d2 --- /dev/null +++ b/sources/PhysX/PhysX/include/vehicle/PxVehicleUtil.h @@ -0,0 +1,64 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_VEHICLE_UTILHELPER_H +#define PX_VEHICLE_UTILHELPER_H +/** \addtogroup vehicle + @{ +*/ + +#include "foundation/Px.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +struct PxVehicleWheelQueryResult; + +/** +\brief Test if all wheels of a vehicle are in the air by querying the wheel query data +stored in the last call to PxVehicleUpdates. If all wheels are in the air then true is returned. + +\note False is returned if any wheel can reach to the ground. + +\note If vehWheelQueryResults.wheelQueryResults is NULL or vehWheelQueryResults.nbWheelQueryResults is 0 then true is returned. +This function does not account for wheels that have been disabled since the last execution of PxVehicleUpdates so it is possible +that wheels disabled more recently than the last call to PxVehicleUpdates report are treated as touching the ground. + +\return True if the vehicle is in the air, false if any wheel is touching the ground. +*/ +bool PxVehicleIsInAir(const PxVehicleWheelQueryResult& vehWheelQueryResults); + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif //PX_VEHICLE_UTILHELPER_H diff --git a/sources/PhysX/PhysX/include/vehicle/PxVehicleUtilControl.h b/sources/PhysX/PhysX/include/vehicle/PxVehicleUtilControl.h new file mode 100644 index 00000000..62a86cff --- /dev/null +++ b/sources/PhysX/PhysX/include/vehicle/PxVehicleUtilControl.h @@ -0,0 +1,651 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_VEHICLE_CONTROL_H +#define PX_VEHICLE_CONTROL_H +/** \addtogroup vehicle + @{ +*/ +#include "vehicle/PxVehicleSDK.h" +#include "vehicle/PxVehicleDrive4W.h" +#include "vehicle/PxVehicleDriveNW.h" +#include "vehicle/PxVehicleDriveTank.h" + + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +#if PX_CHECKED + void testValidAnalogValue(const PxF32 actualValue, const PxF32 minVal, const PxF32 maxVal, const char* errorString); +#endif + +/** +\brief Used to produce smooth vehicle driving control values from key inputs. +@see PxVehicle4WSmoothDigitalRawInputsAndSetAnalogInputs, PxVehicle4WSmoothAnalogRawInputsAndSetAnalogInputs +*/ +struct PxVehicleKeySmoothingData +{ +public: + + /** + \brief Rise rate of each analog value if digital value is 1 + */ + PxReal mRiseRates[PxVehicleDriveDynData::eMAX_NB_ANALOG_INPUTS]; + + /** + \brief Fall rate of each analog value if digital value is 0 + */ + PxReal mFallRates[PxVehicleDriveDynData::eMAX_NB_ANALOG_INPUTS]; +}; +PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleKeySmoothingData)& 0x0f)); + +/** +\brief Used to produce smooth analog vehicle control values from analog inputs. +@see PxVehicleDrive4WSmoothDigitalRawInputsAndSetAnalogInputs, PxVehicleDrive4WSmoothAnalogRawInputsAndSetAnalogInputs +*/ +struct PxVehiclePadSmoothingData +{ +public: + + /** + \brief Rise rate of each analog value from previous value towards target if target>previous + */ + PxReal mRiseRates[PxVehicleDriveDynData::eMAX_NB_ANALOG_INPUTS]; + + /** + \brief Rise rate of each analog value from previous value towards target if target& steerVsForwardSpeedTable, + const PxVehicleDrive4WRawInputData& rawInputData, + const PxReal timestep, + const bool isVehicleInAir, + PxVehicleDrive4W& focusVehicle); + +/** +\brief Used to smooth and set analog vehicle control values from analog inputs (gamepad). +Also used to set boolean gearup, geardown values. +\param[in] padSmoothing describes how quickly the control values applied to the vehicle blend from the current vehicle values towards the raw analog values from the gamepad. +\param[in] steerVsForwardSpeedTable is a table of maximum allowed steer versus forward vehicle speed. +\param[in] rawInputData is the state of all gamepad analog inputs that will be used control the vehicle. +\param[in] timestep is the time that has passed since the last call to PxVehicleDrive4WSmoothDigitalRawInputsAndSetAnalogInputs +\param[in] isVehicleInAir describes if the vehicle is in the air or on the ground and is used to decide whether or not to apply steerVsForwardSpeedTable. +\param[in] focusVehicle is the vehicle that will be given analog control values arising from the gamepad inputs. +*/ +void PxVehicleDrive4WSmoothAnalogRawInputsAndSetAnalogInputs + (const PxVehiclePadSmoothingData& padSmoothing, const PxFixedSizeLookupTable<8>& steerVsForwardSpeedTable, + const PxVehicleDrive4WRawInputData& rawInputData, + const PxReal timestep, + const bool isVehicleInAir, + PxVehicleDrive4W& focusVehicle); + + +/** +\brief Used to produce smooth vehicle driving control values from analog and digital inputs. +@see PxVehicleDriveNWSmoothDigitalRawInputsAndSetAnalogInputs, PxVehicleDriveNWSmoothAnalogRawInputsAndSetAnalogInputs +*/ +class PxVehicleDriveNWRawInputData : public PxVehicleDrive4WRawInputData +{ +public: + + PxVehicleDriveNWRawInputData() : PxVehicleDrive4WRawInputData(){} + ~PxVehicleDriveNWRawInputData(){} +}; + +/** +\brief Used to smooth and set analog vehicle control values (accel,brake,handbrake,steer) from digital inputs (keyboard). + Also used to set boolean gearup, geardown values. + \param[in] keySmoothing describes the rise and fall rates of the corresponding analog values when keys are pressed on and off. + \param[in] steerVsForwardSpeedTable is a table of maximum allowed steer versus forward vehicle speed. + \param[in] rawInputData is the state of all digital inputs that control the vehicle. + \param[in] timestep is the time that has passed since the last call to PxVehicleDrive4WSmoothDigitalRawInputsAndSetAnalogInputs + \param[in] isVehicleInAir describes if the vehicle is in the air or on the ground and is used to decide whether or not to apply steerVsForwardSpeedTable. + \param[in] focusVehicle is the vehicle that will be given analog and gearup/geardown control values arising from the digital inputs. +*/ +void PxVehicleDriveNWSmoothDigitalRawInputsAndSetAnalogInputs + (const PxVehicleKeySmoothingData& keySmoothing, const PxFixedSizeLookupTable<8>& steerVsForwardSpeedTable, + const PxVehicleDriveNWRawInputData& rawInputData, + const PxReal timestep, + const bool isVehicleInAir, + PxVehicleDriveNW& focusVehicle); + +/** +\brief Used to smooth and set analog vehicle control values from analog inputs (gamepad). +Also used to set boolean gearup, geardown values. +\param[in] padSmoothing describes how quickly the control values applied to the vehicle blend from the current vehicle values towards the raw analog values from the gamepad. +\param[in] steerVsForwardSpeedTable is a table of maximum allowed steer versus forward vehicle speed. +\param[in] rawInputData is the state of all gamepad analog inputs that will be used control the vehicle. +\param[in] timestep is the time that has passed since the last call to PxVehicleDrive4WSmoothDigitalRawInputsAndSetAnalogInputs +\param[in] isVehicleInAir describes if the vehicle is in the air or on the ground and is used to decide whether or not to apply steerVsForwardSpeedTable. +\param[in] focusVehicle is the vehicle that will be given analog control values arising from the gamepad inputs. +*/ +void PxVehicleDriveNWSmoothAnalogRawInputsAndSetAnalogInputs + (const PxVehiclePadSmoothingData& padSmoothing, const PxFixedSizeLookupTable<8>& steerVsForwardSpeedTable, + const PxVehicleDriveNWRawInputData& rawInputData, + const PxReal timestep, + const bool isVehicleInAir, + PxVehicleDriveNW& focusVehicle); + + +/** +\brief Used to produce smooth analog tank control values from analog and digital inputs. +@see PxVehicleDriveTankSmoothDigitalRawInputsAndSetAnalogInputs, PxVehicleDriveTankSmoothAnalogRawInputsAndSetAnalogInputs +*/ +class PxVehicleDriveTankRawInputData +{ +public: + + PxVehicleDriveTankRawInputData(const PxVehicleDriveTankControlModel::Enum mode) + : mMode(mode) + { + for(PxU32 i=0;iRange: (0,1)
+ */ + PxReal mPosX; + + /** + \brief y-coord of graph centre. + Range: (0,1)
+ */ + PxReal mPosY; + + /** + \brief x-extents of graph (from mPosX-0.5f*mSizeX to mPosX+0.5f*mSizeX). + Range: (0,1)
+ */ + PxReal mSizeX; + + /** + \brief y-extents of graph (from mPosY-0.5f*mSizeY to mPosY+0.5f*mSizeY). + Range: (0,1)
+ */ + PxReal mSizeY; + + /** + \brief Background color of graph. + */ + PxVec3 mBackgroundColor; + + /** + \brief Alpha value of background color. + */ + PxReal mAlpha; + +private: + + bool isValid() const; +}; + +struct PxVehicleGraphChannelDesc +{ +public: + + friend class PxVehicleGraph; + + PxVehicleGraphChannelDesc(); + + /** + \brief Data values less than mMinY will be clamped at mMinY. + */ + PxReal mMinY; + + /** + \brief Data values greater than mMaxY will be clamped at mMaxY. + */ + PxReal mMaxY; + + /** + \brief Data values greater than mMidY will be drawn with color mColorHigh. + Data values less than mMidY will be drawn with color mColorLow. + */ + PxReal mMidY; + + /** + \brief Color used to render data values lower than mMidY. + */ + PxVec3 mColorLow; + + /** + \brief Color used to render data values greater than mMidY. + */ + PxVec3 mColorHigh; + + /** + \brief String to describe data channel. + */ + char* mTitle; + +private: + + bool isValid() const; +}; + +struct PxVehicleWheelGraphChannel +{ + enum Enum + { + eJOUNCE=0, + eSUSPFORCE, + eTIRELOAD, + eNORMALIZED_TIRELOAD, + eWHEEL_OMEGA, + eTIRE_FRICTION, + eTIRE_LONG_SLIP, + eNORM_TIRE_LONG_FORCE, + eTIRE_LAT_SLIP, + eNORM_TIRE_LAT_FORCE, + eNORM_TIRE_ALIGNING_MOMENT, + eMAX_NB_WHEEL_CHANNELS + }; +}; + +struct PxVehicleDriveGraphChannel +{ + enum Enum + { + eENGINE_REVS=0, + eENGINE_DRIVE_TORQUE, + eCLUTCH_SLIP, + eACCEL_CONTROL, //TANK_ACCEL + eBRAKE_CONTROL, //TANK_BRAKE_LEFT + eHANDBRAKE_CONTROL, //TANK_BRAKE_RIGHT + eSTEER_LEFT_CONTROL, //TANK_THRUST_LEFT + eSTEER_RIGHT_CONTROL, //TANK_THRUST_RIGHT + eGEAR_RATIO, + eMAX_NB_DRIVE_CHANNELS + }; +}; + +struct PxVehicleGraphType +{ + enum Enum + { + eWHEEL=0, + eDRIVE + }; +}; + + +class PxVehicleGraph +{ +public: + + friend class PxVehicleTelemetryData; + friend class PxVehicleUpdate; + + enum + { + eMAX_NB_SAMPLES=256 + }; + + enum + { + eMAX_NB_TITLE_CHARS=256 + }; + + enum + { + eMAX_NB_CHANNELS=12 + }; + + /** + \brief Setup a graph from a descriptor. + */ + void setup(const PxVehicleGraphDesc& desc, const PxVehicleGraphType::Enum graphType); + + /** + \brief Clear all data recorded in a graph. + */ + void clearRecordedChannelData(); + + /** + \brief Get the color of the graph background. Used for rendering a graph. + */ + const PxVec3& getBackgroundColor() const {return mBackgroundColor;} + + /** + \brief Get the alpha transparency of the color of the graph background. Used for rendering a graph. + */ + PxReal getBackgroundAlpha() const {return mBackgroundAlpha;} + + /** + \brief Get the coordinates of the graph background. Used for rendering a graph + + \param[out] xMin is the x-coord of the lower-left corner + \param[out] yMin is the y-coord of the lower-left corner + \param[out] xMax is the x-coord of the upper-right corner + \param[out] yMax is the y-coord of the upper-right corner + */ + void getBackgroundCoords(PxReal& xMin, PxReal& yMin, PxReal& xMax, PxReal& yMax) const {xMin = mBackgroundMinX;xMax = mBackgroundMaxX;yMin = mBackgroundMinY;yMax = mBackgroundMaxY;} + + /** + \brief Compute the coordinates of the graph data of a specific graph channel. + + \param[out] xy is an array of graph sample coordinates stored in order x0,y0,x1,y1,x2,y2...xn,yn. + \param[out] colors stores the color of each point on the graph. + \param[out] title is the title of the graph. + */ + void computeGraphChannel(const PxU32 channel, PxReal* xy, PxVec3* colors, char* title) const; + + /** + \brief Return the latest value stored in the specified graph channel + */ + PxF32 getLatestValue(const PxU32 channel) const ; + +private: + + //Min and max of each sample. + PxReal mChannelMinY[eMAX_NB_CHANNELS]; + PxReal mChannelMaxY[eMAX_NB_CHANNELS]; + //Discriminate between high and low values with different colors. + PxReal mChannelMidY[eMAX_NB_CHANNELS]; + //Different colors for values than midY and less than midY. + PxVec3 mChannelColorLow[eMAX_NB_CHANNELS]; + PxVec3 mChannelColorHigh[eMAX_NB_CHANNELS]; + //Title of graph + char mChannelTitle[eMAX_NB_CHANNELS][eMAX_NB_TITLE_CHARS]; + //Graph data. + PxReal mChannelSamples[eMAX_NB_CHANNELS][eMAX_NB_SAMPLES]; + + //Background color,alpha,coords + PxVec3 mBackgroundColor; + PxReal mBackgroundAlpha; + PxReal mBackgroundMinX; + PxReal mBackgroundMaxX; + PxReal mBackgroundMinY; + PxReal mBackgroundMaxY; + + PxU32 mSampleTide; + + PxU32 mNbChannels; + + PxU32 mPad[2]; + + + void setup + (const PxF32 graphSizeX, const PxF32 graphSizeY, + const PxF32 engineGraphPosX, const PxF32 engineGraphPosY, + const PxF32* const wheelGraphPosX, const PxF32* const wheelGraphPosY, + const PxVec3& backgroundColor, const PxVec3& lineColorHigh, const PxVec3& lineColorLow); + + void updateTimeSlice(const PxReal* const samples); + + void setChannel(PxVehicleGraphChannelDesc& desc, const PxU32 channel); + + void setupEngineGraph + (const PxF32 sizeX, const PxF32 sizeY, const PxF32 posX, const PxF32 posY, + const PxVec3& backgoundColor, const PxVec3& lineColorHigh, const PxVec3& lineColorLow); + + void setupWheelGraph + (const PxF32 sizeX, const PxF32 sizeY, const PxF32 posX, const PxF32 posY, + const PxVec3& backgoundColor, const PxVec3& lineColorHigh, const PxVec3& lineColorLow); + + PxVehicleGraph(); + ~PxVehicleGraph(); +}; +PX_COMPILE_TIME_ASSERT(PxU32(PxVehicleGraph::eMAX_NB_CHANNELS) >= PxU32(PxVehicleWheelGraphChannel::eMAX_NB_WHEEL_CHANNELS) && PxU32(PxVehicleGraph::eMAX_NB_CHANNELS) >= PxU32(PxVehicleDriveGraphChannel::eMAX_NB_DRIVE_CHANNELS)); +PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleGraph) & 15)); + +class PxVehicleTelemetryData +{ +public: + + friend class PxVehicleUpdate; + + /** + \brief Allocate a PxVehicleNWTelemetryData instance for a vehicle with nbWheels + @see PxVehicleNWTelemetryDataFree + */ + static PxVehicleTelemetryData* allocate(const PxU32 nbWheels); + + /** + \brief Free a PxVehicleNWTelemetryData instance for a vehicle. + @see PxVehicleNWTelemetryDataAllocate + */ + void free(); + + /** + \brief Set up all the graphs so that they are ready to record data. + */ + void setup + (const PxReal graphSizeX, const PxReal graphSizeY, + const PxReal engineGraphPosX, const PxReal engineGraphPosY, + const PxReal* const wheelGraphPosX, const PxReal* const wheelGraphPosY, + const PxVec3& backGroundColor, const PxVec3& lineColorHigh, const PxVec3& lineColorLow); + + /** + \brief Clear the graphs of recorded data. + */ + void clear(); + + /** + \brief Get the graph data for the engine + */ + const PxVehicleGraph& getEngineGraph() const {return *mEngineGraph;} + + /** + \brief Get the number of wheel graphs + */ + PxU32 getNbWheelGraphs() const {return mNbActiveWheels;} + + /** + \brief Get the graph data for the kth wheel + */ + const PxVehicleGraph& getWheelGraph(const PxU32 k) const {return mWheelGraphs[k];} + + /** + \brief Get the array of tire force application points so they can be rendered + */ + const PxVec3* getTireforceAppPoints() const {return mTireforceAppPoints;} + + /** + \brief Get the array of susp force application points so they can be rendered + */ + const PxVec3* getSuspforceAppPoints() const {return mSuspforceAppPoints;} + +private: + + /** + \brief Graph data for engine. + Used for storing single timeslices of debug data for engine graph. + @see PxVehicleGraph + */ + PxVehicleGraph* mEngineGraph; + + /** + \brief Graph data for each wheel. + Used for storing single timeslices of debug data for wheel graphs. + @see PxVehicleGraph + */ + PxVehicleGraph* mWheelGraphs; + + /** + \brief Application point of tire forces. + */ + PxVec3* mTireforceAppPoints; + + /** + \brief Application point of susp forces. + */ + PxVec3* mSuspforceAppPoints; + + /** + \brief Total number of active wheels + */ + PxU32 mNbActiveWheels; + + PxU32 mPad[3]; + +private: + + PxVehicleTelemetryData(){} + ~PxVehicleTelemetryData(){} +}; + +PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleTelemetryData) & 15)); + +#endif //PX_DEBUG_VEHICLE_ON + +//#endif // PX_DEBUG_VEHICLE_ON + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif //PX_VEHICLE_UTILSTELEMETRY_H diff --git a/sources/PhysX/PhysX/include/vehicle/PxVehicleWheels.h b/sources/PhysX/PhysX/include/vehicle/PxVehicleWheels.h new file mode 100644 index 00000000..322701c4 --- /dev/null +++ b/sources/PhysX/PhysX/include/vehicle/PxVehicleWheels.h @@ -0,0 +1,874 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_VEHICLE_WHEELS_H +#define PX_VEHICLE_WHEELS_H +/** \addtogroup vehicle + @{ +*/ + +#include "foundation/PxSimpleTypes.h" +#include "vehicle/PxVehicleShaders.h" +#include "vehicle/PxVehicleComponents.h" +#include "common/PxBase.h" +#include "PxRigidDynamic.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxVehicleWheels4SimData; +class PxVehicleWheels4DynData; +class PxVehicleTireForceCalculator; +class PxShape; +class PxPhysics; +class PxMaterial; + +/** +\brief Flags to configure the vehicle wheel simulation. + +@see PxVehicleWheelsSimData::setFlags(), PxVehicleWheelsSimData::getFlags() +*/ +struct PxVehicleWheelsSimFlag +{ + enum Enum + { + /** + \brief Limit the suspension expansion velocity. + + For extreme damping ratios, large damping forces might result in the vehicle sticking to the ground where + one would rather expect to see the vehicle lift off. While it is highly recommended to use somewhat realistic + damping ratios, this flag can be used to limit the velocity of the suspension. In more detail, the simulation + will check whether the suspension can extend to the target length in the given simulation time step. If that + is the case, the suspension force will be computed as usual, else the force will be set to zero. Enabling + this feature gives a slightly more realisitic behavior at the potential cost of more easily losing control + when steering the vehicle. + */ + eLIMIT_SUSPENSION_EXPANSION_VELOCITY = (1 << 0) + }; +}; + +/** +\brief Collection of set bits defined in #PxVehicleWheelsSimFlag. + +@see PxVehicleWheelsSimFlag +*/ +typedef PxFlags PxVehicleWheelsSimFlags; +PX_FLAGS_OPERATORS(PxVehicleWheelsSimFlag::Enum, PxU32) + +/** +\brief Data structure describing configuration data of a vehicle with up to 20 wheels. +*/ + +class PxVehicleWheelsSimData +{ +//= ATTENTION! ===================================================================================== +// Changing the data layout of this class breaks the binary serialization format. See comments for +// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData +// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION +// accordingly. +//================================================================================================== +public: + + friend class PxVehicleWheels; + friend class PxVehicleNoDrive; + friend class PxVehicleDrive4W; + friend class PxVehicleDriveTank; + friend class PxVehicleUpdate; + + /** + \brief Allocate a PxVehicleWheelsSimData instance for with nbWheels. + @see free + */ + static PxVehicleWheelsSimData* allocate(const PxU32 nbWheels); + + /** + \brief Setup with mass information that can be applied to the default values of the suspensions, wheels, and tires + set in their respective constructors. + + \param chassisMass is the mass of the chassis. + + \note This function assumes that the suspensions equally share the load of the chassis mass. It also + assumes that the suspension will have a particular natural frequency and damping ratio that is typical + of a standard car. If either of these assumptions is broken then each suspension will need to + be individually configured with custom strength, damping rate, and sprung mass. + + @see allocate + */ + void setChassisMass(const PxF32 chassisMass); + + /** + \brief Free a PxVehicleWheelsSimData instance + @see allocate + */ + void free(); + + /** + \brief Copy wheel simulation data. + \note The number of wheels on both instances of PxVehicleWheelsSimData must match. + */ + PxVehicleWheelsSimData& operator=(const PxVehicleWheelsSimData& src); + + /** + \brief Copy the data of a single wheel unit (wheel, suspension, tire) from srcWheel of src to trgWheel. + \param[in] src is the data to be copied. + \param[in] srcWheel is the wheel whose data will be copied from src. + \param[in] trgWheel is the wheel that will be assigned the copied data. + */ + void copy(const PxVehicleWheelsSimData& src, const PxU32 srcWheel, const PxU32 trgWheel); + + /** + \brief Return the number of wheels + @see allocate + */ + PxU32 getNbWheels() const {return mNbActiveWheels;} + + /** + \brief Return the suspension data of the idth wheel + */ + const PxVehicleSuspensionData& getSuspensionData(const PxU32 id) const; + + /** + \brief Return the wheel data of the idth wheel + */ + const PxVehicleWheelData& getWheelData(const PxU32 id) const; + + /** + \brief Return the tire data of the idth wheel + */ + const PxVehicleTireData& getTireData(const PxU32 id) const; + + /** + \brief Return the direction of travel of the suspension of the idth wheel + */ + const PxVec3& getSuspTravelDirection(const PxU32 id) const; + + /** + \brief Return the application point of the suspension force of the suspension of the idth wheel as an offset from the rigid body center of mass. + \note Specified relative to the center of mass of the rigid body + */ + const PxVec3& getSuspForceAppPointOffset(const PxU32 id) const; + + /** + \brief Return the application point of the tire force of the tire of the idth wheel as an offset from the rigid body center of mass. + \note Specified relative to the centre of mass of the rigid body + */ + const PxVec3& getTireForceAppPointOffset(const PxU32 id) const; + + /** + \brief Return the offset from the rigid body centre of mass to the centre of the idth wheel. + */ + const PxVec3& getWheelCentreOffset(const PxU32 id) const; + + /** + \brief Return the wheel mapping for the ith wheel. + + \note The return value is the element in the array of + shapes of the vehicle's PxRigidDynamic that corresponds to the ith wheel. A return value of -1 means + that the wheel is not mapped to a PxShape. + + @see PxRigidActor.getShapes + */ + PxI32 getWheelShapeMapping(const PxU32 wheelId) const; + + /** + \brief Return the scene query filter data used by the specified suspension line + */ + const PxFilterData& getSceneQueryFilterData(const PxU32 suspId) const; + + /** + \brief Return the number of unique anti-roll bars that have been added with addAntiRollBarData + @see PxVehicleWheelsSimData::addAntiRollBarData + */ + PxU32 getNbAntiRollBars() const + { + return mNbActiveAntiRollBars; + } + + /** + \brief Return a specific anti-roll bar. + \param antiRollId is the unique id of the anti-roll bar + \note The return value of addAntiRollBarData is a unique id for that specific anti-roll bar + and can be used as input parameter for getAntiRollBarData in order to query the same anti-roll bar. + Alternatively, it is possible to iterate over all anti-roll bars by choosing antiRollId + in range (0, getNbAntiRollBars()). + */ + const PxVehicleAntiRollBarData& getAntiRollBarData(const PxU32 antiRollId) const; + + /** + \brief Return the data that describes the filtering of the tire load to produce smoother handling at large time-steps. + */ + PX_FORCE_INLINE const PxVehicleTireLoadFilterData& getTireLoadFilterData() const + { + return mNormalisedLoadFilter; + } + + /** + \brief Set the suspension data of the idth wheel + \param[in] id is the wheel index. + \param[in] susp is the suspension data to be applied. + */ + void setSuspensionData(const PxU32 id, const PxVehicleSuspensionData& susp); + + /** + \brief Set the wheel data of the idth wheel + \param[in] id is the wheel index. + \param[in] wheel is the wheel data to be applied. + */ + void setWheelData(const PxU32 id, const PxVehicleWheelData& wheel); + + /** + \brief Set the tire data of the idth wheel + \param[in] id is the wheel index. + \param[in] tire is the tire data to be applied. + */ + void setTireData(const PxU32 id, const PxVehicleTireData& tire); + + /** + \brief Set the direction of travel of the suspension of the idth wheel + \param[in] id is the wheel index + \param[in] dir is the suspension travel direction to be applied. + */ + void setSuspTravelDirection(const PxU32 id, const PxVec3& dir); + + /** + \brief Set the application point of the suspension force of the suspension of the idth wheel. + \param[in] id is the wheel index + \param[in] offset is the offset from the rigid body center of mass to the application point of the suspension force. + \note Specified relative to the centre of mass of the rigid body + */ + void setSuspForceAppPointOffset(const PxU32 id, const PxVec3& offset); + + /** + \brief Set the application point of the tire force of the tire of the idth wheel. + \param[in] id is the wheel index + \param[in] offset is the offset from the rigid body center of mass to the application point of the tire force. + \note Specified relative to the centre of mass of the rigid body + */ + void setTireForceAppPointOffset(const PxU32 id, const PxVec3& offset); + + /** + \brief Set the offset from the rigid body centre of mass to the centre of the idth wheel. + \param[in] id is the wheel index + \param[in] offset is the offset from the rigid body center of mass to the center of the wheel at rest. + \note Specified relative to the centre of mass of the rigid body + */ + void setWheelCentreOffset(const PxU32 id, const PxVec3& offset); + + /** + \brief Set mapping between wheel id and position of corresponding wheel shape in the list of actor shapes. + + \note This mapping is used to pose the correct wheel shapes with the latest wheel rotation angle, steer angle, and suspension travel + while allowing arbitrary ordering of the wheel shapes in the actor's list of shapes. + + \note Use setWheelShapeMapping(i,-1) to register that there is no wheel shape corresponding to the ith wheel + + \note Set setWheelShapeMapping(i,k) to register that the ith wheel corresponds to the kth shape in the actor's list of shapes. + + \note The default values correspond to setWheelShapeMapping(i,i) for all wheels. + + \note Calling this function will also pose the relevant PxShape at the rest position of the wheel. + + \param wheelId is the wheel index + + \param shapeId is the shape index. + + @see PxVehicleUpdates, PxVehicleDrive4W::setup, PxVehicleDriveTank::setup, PxVehicleNoDrive::setup, setSceneQueryFilterData, PxRigidActor::getShapes + */ + void setWheelShapeMapping(const PxU32 wheelId, const PxI32 shapeId); + + /** + \brief Set the scene query filter data that will be used for raycasts along the travel + direction of the specified suspension. The default value is PxFilterData(0,0,0,0) + \param suspId is the wheel index + \param sqFilterData is the raycast filter data for the suspension raycast. + @see setWheelShapeMapping + */ + void setSceneQueryFilterData(const PxU32 suspId, const PxFilterData& sqFilterData); + + /** + \brief Set the data that describes the filtering of the tire load to produce smoother handling at large timesteps. + \param tireLoadFilter is the smoothing function data. + */ + void setTireLoadFilterData(const PxVehicleTireLoadFilterData& tireLoadFilter); + + /** + \brief Set the anti-roll suspension for a pair of wheels. + + \param antiRoll is the anti-roll suspension. + + \note If an anti-roll bar has already been set for the same logical wheel pair + (independent of wheel index order specified by PxVehicleAntiRollBar.mWheel0 and PxVehicleAntiRollBar.mWheel0) + then the existing anti-roll bar is updated with a new stiffness parameter antiRoll.mStiffness. + + \note If the wheel pair specified by antiRoll does not yet have an anti-roll bar then antiRoll is added to + a list of anti-roll bars for the vehicle. + + \return If antiRoll represents a new wheel pair then a unique id is assigned to the anti-roll bar and returned. + If antiRoll represents an existing wheel pair then the unique id of the existing anti-roll bar is returned. + The return value is always in range (0, getNbAntiRollBars()). + + \note The return value can be used to query the anti-roll bar with getAntiRollBarData(id). + + \note The number of possible anti-roll bars is limited to half the wheel count. + + \note An existing anti-roll bar can be disabled by calling antiRoll.mStiffness to zero. + + @see PxVehicleWheelsSimData::getAntiRollBarData, PxVehicleAntiRollBarData + */ + PxU32 addAntiRollBarData(const PxVehicleAntiRollBarData& antiRoll); + + /** + \brief Disable a wheel so that zero suspension forces and zero tire forces are applied to the rigid body from this wheel. + + \note If the vehicle has a differential (PxVehicleNW/PxVehicle4W) then the differential (PxVehicleDifferentialNWData/PxVehicleDifferential4WData) + needs to be configured so that no drive torque is delivered to the disabled wheel. + + \note If the vehicle is of type PxVehicleNoDrive then zero drive torque must be applied to the disabled wheel. + + \note For tanks (PxVehicleDriveTank) any drive torque that could be delivered to the wheel through the tank differential will be + re-directed to the remaining enabled wheels. + + @see enableWheel + @see PxVehicleDifferentialNWData::setDrivenWheel + @see PxVehicleDifferential4WData::mFrontLeftRightSplit, PxVehicleDifferential4WData::mRearLeftRightSplit, PxVehicleDifferential4WData::mType + @see PxVehicleNoDrive::setDriveTorque + @see PxVehicle4WEnable3WTadpoleMode, PxVehicle4WEnable3WDeltaMode + + \note If a PxShape is associated with the disabled wheel then the association must be broken by calling setWheelShapeMapping(wheelId, -1). + @see setWheelShapeMapping + + \note A wheel that is disabled must also simultaneously be given zero wheel rotation speed. + @see PxVehicleWheelsDynData::setWheelRotationSpeed + + \note Care must be taken with the sprung mass supported by the remaining enabled wheels. Depending on the desired effect, the mass of the rigid body + might need to be distributed among the remaining enabled wheels and suspensions. + + \param[in] wheel is the wheel index. + */ + void disableWheel(const PxU32 wheel); + + /** + \brief Enable a wheel so that suspension forces and tire forces are applied to the rigid body. + All wheels are enabled by default and remain enabled until they are disabled. + \param[in] wheel is the wheel index. + @see disableWheel + */ + void enableWheel(const PxU32 wheel); + + /** + \brief Test if a wheel has been disabled. + \param[in] wheel is the wheel index. + */ + bool getIsWheelDisabled(const PxU32 wheel) const; + + /** + \brief Set the number of vehicle sub-steps that will be performed when the vehicle's longitudinal + speed is below and above a threshold longitudinal speed. + + \note More sub-steps provides better stability but with greater computational cost. + + \note Typically, vehicles require more sub-steps at very low forward speeds. + + \note The threshold longitudinal speed has a default value that is the equivalent of 5 metres per second after accounting for + the length scale set in PxTolerancesScale. + + \note The sub-step count below the threshold longitudinal speed has a default of 3. + + \note The sub-step count above the threshold longitudinal speed has a default of 1. + + \note Each sub-step has time advancement equal to the time-step passed to PxVehicleUpdates divided by the number of required sub-steps. + + \note The contact planes of the most recent suspension line raycast are reused across all sub-steps. + + \note Each sub-step computes tire and suspension forces and then advances a velocity, angular velocity and transform. + + \note At the end of all sub-steps the vehicle actor is given the velocity and angular velocity that would move the actor from its start transform prior + to the first sub-step to the transform computed at the end of the last substep, assuming it doesn't collide with anything along the way in the next PhysX SDK update. + + \note The global pose of the actor is left unchanged throughout the sub-steps. + + \param[in] thresholdLongitudinalSpeed is a threshold speed that is used to categorize vehicle speed as low speed or high speed. + \param[in] lowForwardSpeedSubStepCount is the number of sub-steps performed in PxVehicleUpates for vehicles that have longitudinal speed lower than thresholdLongitudinalSpeed. + \param[in] highForwardSpeedSubStepCount is the number of sub-steps performed in PxVehicleUpdates for vehicles that have longitudinal speed graeter than thresholdLongitudinalSpeed. + */ + void setSubStepCount(const PxReal thresholdLongitudinalSpeed, const PxU32 lowForwardSpeedSubStepCount, const PxU32 highForwardSpeedSubStepCount); + + /** + \brief Set the minimum denominator used in the longitudinal slip calculation. + + \note The longitudinal slip has a theoretical value of (w*r - vz)/|vz|, where w is the angular speed of the wheel; r is the radius of the wheel; + and vz is the component of rigid body velocity (computed at the wheel base) that lies along the longitudinal wheel direction. The term |vz| + normalizes the slip, while preserving the sign of the longitudinal tire slip. The difficulty here is that when |vz| approaches zero the + longitudinal slip approaches infinity. A solution to this problem is to replace the denominator (|vz|) with a value that never falls below a chosen threshold. + The longitudinal slip is then calculated with (w*r - vz)/PxMax(|vz|, minLongSlipDenominator). + + \note The default value is the equivalent of 4 metres per second after accounting for the length scale set in PxTolerancesScale. + + \note Adjust this value upwards if a vehicle has difficulty coming to rest. + + \note Decreasing the timestep (or increasing the number of sub-steps at low longitudinal speed with setSubStepCount) should allow stable stable + behavior with smaller values of minLongSlipDenominator. + */ + void setMinLongSlipDenominator(const PxReal minLongSlipDenominator); + + /** + \brief Set the vehicle wheel simulation flags. + + \param[in] flags The flags to set (see #PxVehicleWheelsSimFlags). + + Default: no flag set + + @see PxVehicleWheelsSimFlag + */ + void setFlags(PxVehicleWheelsSimFlags flags); + + /** + \brief Return the vehicle wheel simulation flags. + + \return The values of the flags. + + @see PxVehicleWheelsSimFlag + */ + PxVehicleWheelsSimFlags getFlags() const; + +private: + + /** + \brief Graph to filter normalised load + @see setTireLoadFilterData, getTireLoadFilterData + */ + PxVehicleTireLoadFilterData mNormalisedLoadFilter; + + /** + \brief Wheels data organised in blocks of 4 wheels. + */ + PxVehicleWheels4SimData* mWheels4SimData; + + /** + \brief Number of blocks of 4 wheels. + */ + PxU32 mNbWheels4; + + /** + \brief Number of actual wheels (<=(mNbWheels4*4)) + */ + PxU32 mNbActiveWheels; + + /** + \brief Anti-roll bars + */ + PxVehicleAntiRollBarData* mAntiRollBars; + + /** + \brief 2 anti-rollbars allocated for each block of 4 wheels. + */ + PxU32 mNbAntiRollBars4; + + /** + \brief Number of active anti-roll bars. + */ + PxU32 mNbActiveAntiRollBars; + + /** + \brief Which of the mNbActiveWheels are active or disabled? + The default is that all mNbActiveWheels wheels are active. + */ + PxU32 mActiveWheelsBitmapBuffer[((PX_MAX_NB_WHEELS + 31) & ~31) >> 5]; + + /** + \brief Threshold longitudinal speed used to decide whether to use + mLowForwardSpeedSubStepCount or mHighForwardSpeedSubStepCount as the + number of sub-steps that will be peformed. + */ + PxF32 mThresholdLongitudinalSpeed; + + /** + \brief Number of sub-steps that will be performed if the longitudinal speed + of the vehicle is smaller than mThresholdLongitudinalSpeed. + */ + PxU32 mLowForwardSpeedSubStepCount; + + /** + \brief Number of sub-steps that will be performed if the longitudinal speed + of the vehicle is greater than or equal to mThresholdLongitudinalSpeed. + */ + PxU32 mHighForwardSpeedSubStepCount; + + /** + \brief Minimum long slip denominator + */ + PxF32 mMinLongSlipDenominator; + + /** + \brief The vehicle wheel simulation flags. + + @see PxVehicleWheelsSimFlags + */ + PxU32 mFlags; + +#if PX_P64_FAMILY + PxU32 mPad[1]; +#endif + + /** + \brief Test if wheel simulation data has been setup with legal values. + */ + bool isValid() const; + + /** + \brief see PxVehicleWheels::allocate + */ + static PxU32 computeByteSize(const PxU32 numWheels); + static PxU8* patchUpPointers(const PxU32 numWheels, PxVehicleWheelsSimData* simData, PxU8* ptrIn); + PxVehicleWheelsSimData(const PxU32 numWheels); + +//serialization +public: + PxVehicleWheelsSimData(const PxEMPTY) : mNormalisedLoadFilter(PxEmpty) {} + static void getBinaryMetaData(PxOutputStream& stream); + PxU32 getNbWheels4() const { return mNbWheels4; } + PxU32 getNbSuspensionData() const { return mNbActiveWheels; } + PxU32 getNbWheelData() const { return mNbActiveWheels; } + PxU32 getNbSuspTravelDirection() const { return mNbActiveWheels; } + PxU32 getNbTireData() const { return mNbActiveWheels; } + PxU32 getNbSuspForceAppPointOffset() const { return mNbActiveWheels; } + PxU32 getNbTireForceAppPointOffset() const { return mNbActiveWheels; } + PxU32 getNbWheelCentreOffset() const { return mNbActiveWheels; } + PxU32 getNbWheelShapeMapping() const { return mNbActiveWheels; } + PxU32 getNbSceneQueryFilterData() const { return mNbActiveWheels; } + PxF32 getMinLongSlipDenominator() const {return mMinLongSlipDenominator;} + void setThresholdLongSpeed(const PxF32 f) {mThresholdLongitudinalSpeed = f;} + PxF32 getThresholdLongSpeed() const {return mThresholdLongitudinalSpeed;} + void setLowForwardSpeedSubStepCount(const PxU32 f) {mLowForwardSpeedSubStepCount = f;} + PxU32 getLowForwardSpeedSubStepCount() const {return mLowForwardSpeedSubStepCount;} + void setHighForwardSpeedSubStepCount(const PxU32 f) {mHighForwardSpeedSubStepCount = f;} + PxU32 getHighForwardSpeedSubStepCount() const {return mHighForwardSpeedSubStepCount;} + void setWheelEnabledState(const PxU32 wheel, const bool state) {if(state) {enableWheel(wheel);} else {disableWheel(wheel);}} + bool getWheelEnabledState(const PxU32 wheel) const {return !getIsWheelDisabled(wheel);} + PxU32 getNbWheelEnabledState() const {return mNbActiveWheels;} + PxU32 getNbAntiRollBars4() const { return mNbAntiRollBars4; } + PxU32 getNbAntiRollBarData() const {return mNbActiveAntiRollBars;} + void setAntiRollBarData(const PxU32 id, const PxVehicleAntiRollBarData& antiRoll); + PxVehicleWheelsSimData(){} + ~PxVehicleWheelsSimData(){} +//~serialization +}; +PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleWheelsSimData) & 15)); + +/** +\brief Data structure with instanced dynamics data for wheels +*/ +class PxVehicleWheelsDynData +{ +//= ATTENTION! ===================================================================================== +// Changing the data layout of this class breaks the binary serialization format. See comments for +// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData +// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION +// accordingly. +//================================================================================================== +public: + + friend class PxVehicleWheels; + friend class PxVehicleDrive4W; + friend class PxVehicleDriveTank; + friend class PxVehicleUpdate; + + PxVehicleWheelsDynData(){} + ~PxVehicleWheelsDynData(){} + + /** + \brief Set all wheels to their rest state. + @see setup + */ + void setToRestState(); + + /** + \brief Set the tire force shader function + \param[in] tireForceShaderFn is the shader function that will be used to compute tire forces. + */ + void setTireForceShaderFunction(PxVehicleComputeTireForce tireForceShaderFn); + + /** + \brief Set the tire force shader data for a specific tire + \param[in] tireId is the wheel index + \param[in] tireForceShaderData is the data describing the tire. + */ + void setTireForceShaderData(const PxU32 tireId, const void* tireForceShaderData); + + /** + \brief Get the tire force shader data for a specific tire + */ + const void* getTireForceShaderData(const PxU32 tireId) const; + + /** + \brief Set the wheel rotation speed (radians per second) about the rolling axis for the specified wheel. + \param[in] wheelIdx is the wheel index + \param[in] speed is the rotation speed to be applied to the wheel. + */ + void setWheelRotationSpeed(const PxU32 wheelIdx, const PxReal speed); + + /** + \brief Return the rotation speed about the rolling axis of a specified wheel . + */ + PxReal getWheelRotationSpeed(const PxU32 wheelIdx) const; + + /** + \brief Set the wheel rotation angle (radians) about the rolling axis of the specified wheel. + \param[in] wheelIdx is the wheel index + \param[in] angle is the rotation angle to be applied to the wheel. + */ + void setWheelRotationAngle(const PxU32 wheelIdx, const PxReal angle); + + /** + \brief Return the rotation angle about the rolling axis for the specified wheel. + */ + PxReal getWheelRotationAngle(const PxU32 wheelIdx) const; + + /** + \brief Set the user data pointer for the specified wheel + It has a default value of NULL. + \param[in] tireIdx is the wheel index + \param[in] userData is the data to be associated with the wheel. + */ + void setUserData(const PxU32 tireIdx, void* userData); + + /** + \brief Get the user data pointer that was set for the specified wheel + */ + void* getUserData(const PxU32 tireIdx) const; + + /** + \brief Copy the dynamics data of a single wheel unit (wheel, suspension, tire) from srcWheel of src to trgWheel. + \param[in] src is the data to be copied. + \param[in] srcWheel is the wheel whose data will be copied from src. + \param[in] trgWheel is the wheel that will be assigned the copied data. + */ + void copy(const PxVehicleWheelsDynData& src, const PxU32 srcWheel, const PxU32 trgWheel); + +private: + + /** + \brief Dynamics data arranged in blocks of 4 wheels. + */ + PxVehicleWheels4DynData* mWheels4DynData; + + /** + \brief Test if wheel dynamics data have legal values. + */ + bool isValid() const; + + /** + \brief Shader data and function for tire force calculations. + */ + PxVehicleTireForceCalculator* mTireForceCalculators; + + /** + \brief A userData pointer can be stored for each wheel. + @see setUserData, getUserData + */ + void** mUserDatas; + + /** + \brief Number of blocks of 4 wheels. + */ + PxU32 mNbWheels4; + + /** + \brief Number of wheels (mNbActiveWheels <= (mNbWheels4*4)) + */ + PxU32 mNbActiveWheels; + + PxU32 mPad[3]; + + /** + \brief see PxVehicleWheels::allocate + */ + static PxU32 computeByteSize(const PxU32 numWheels); + static PxU8* patchUpPointers(const PxU32 numWheels, PxVehicleWheelsDynData* dynData, PxU8* ptr); + PxVehicleWheelsDynData(const PxU32 numWheels); + +//serialization +public: + static void getBinaryMetaData(PxOutputStream& stream); + PxU32 getNbWheelRotationSpeed() const { return mNbActiveWheels; } + PxU32 getNbWheelRotationAngle() const { return mNbActiveWheels; } + PxVehicleWheels4DynData* getWheel4DynData() const { return mWheels4DynData; } +//~serialization +}; +PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleWheelsDynData) & 15)); + +/** +\brief Data structure with instanced dynamics data and configuration data of a vehicle with just wheels +@see PxVehicleDrive, PxVehicleDrive4W, PxVehicleDriveTank +*/ +class PxVehicleWheels : public PxBase +{ +//= ATTENTION! ===================================================================================== +// Changing the data layout of this class breaks the binary serialization format. See comments for +// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData +// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION +// accordingly. +//================================================================================================== +public: + + friend class PxVehicleUpdate; + friend class PxVehicleConstraintShader; + + /** + \brief Return the type of vehicle + @see PxVehicleTypes + */ + PX_FORCE_INLINE PxU32 getVehicleType() const {return mType;} + + /** + \brief Get non-const ptr to PxRigidDynamic instance that is the vehicle's physx representation + */ + PX_FORCE_INLINE PxRigidDynamic* getRigidDynamicActor() {return mActor;} + + /** + \brief Get const ptr to PxRigidDynamic instance that is the vehicle's physx representation + */ + PX_FORCE_INLINE const PxRigidDynamic* getRigidDynamicActor() const {return mActor;} + + /** + \brief Compute the rigid body velocity component along the forward vector of the rigid body transform. + @see PxVehicleSetBasisVectors + */ + PxReal computeForwardSpeed() const; + + /** + \brief Compute the rigid body velocity component along the right vector of the rigid body transform. + @see PxVehicleSetBasisVectors + */ + PxReal computeSidewaysSpeed() const; + + /** + \brief Data describing the setup of all the wheels/suspensions/tires. + */ + PxVehicleWheelsSimData mWheelsSimData; + + /** + \brief Data describing the dynamic state of all wheels/suspension/tires. + */ + PxVehicleWheelsDynData mWheelsDynData; + +protected: + + /** + \brief Set all wheels to their rest state + */ + void setToRestState(); + + /** + \brief Test that all configuration and instanced dynamics data is valid. + */ + bool isValid() const; + + /** + @see PxVehicleDrive4W::allocate, PxVehicleDriveTank::allocate + */ + static PxU32 computeByteSize(const PxU32 nbWheels); + static PxU8* patchupPointers(const PxU32 nbWheels, PxVehicleWheels* vehWheels, PxU8* ptr); + virtual void init(const PxU32 numWheels); + + /** + \brief Deallocate a PxVehicleWheels instance. + @see PxVehicleDrive4W::free, PxVehicleDriveTank::free + */ + void free(); + + /* + \brief Deferred deletion. + */ + void onConstraintRelease(); + + /** + @see PxVehicleDrive4W::setup, PxVehicleDriveTank::setup + */ + void setup + (PxPhysics* physics, PxRigidDynamic* vehActor, + const PxVehicleWheelsSimData& wheelsData, + const PxU32 nbDrivenWheels, const PxU32 nbNonDrivenWheels); + + /** + \brief The rigid body actor that represents the vehicle in the PhysX SDK. + */ + PxRigidDynamic* mActor; + +private: + + /** + \brief Count the number of constraint connectors that have hit their callback when deleting a vehicle. + Can only delete the vehicle's memory when all constraint connectors have hit their callback. + */ + PxU32 mNbNonDrivenWheels; + + PxU8 mOnConstraintReleaseCounter; + +protected: + + /** + \brief Vehicle type (eVehicleDriveTypes) + */ + PxU8 mType; + +#if PX_P64_FAMILY + PxU8 mPad0[14]; +#else + PxU8 mPad0[14]; +#endif + +//serialization +public: + virtual void requiresObjects(PxProcessPxBaseCallback& c); + virtual const char* getConcreteTypeName() const { return "PxVehicleWheels"; } + virtual bool isKindOf(const char* name) const { return !::strcmp("PxVehicleWheels", name) || PxBase::isKindOf(name); } + virtual void preExportDataReset() {} + virtual void exportExtraData(PxSerializationContext&); + void importExtraData(PxDeserializationContext&); + void resolveReferences(PxDeserializationContext&); + static void getBinaryMetaData(PxOutputStream& stream); + PX_FORCE_INLINE PxU32 getNbNonDrivenWheels() const { return mNbNonDrivenWheels; } + PxVehicleWheels(PxType concreteType, PxBaseFlags baseFlags) : PxBase(concreteType, baseFlags) {} + PxVehicleWheels(PxBaseFlags baseFlags) : PxBase(baseFlags), mWheelsSimData(PxEmpty) {} + virtual ~PxVehicleWheels() {} + virtual void release() { free(); } +//~serialization +}; +PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleWheels) & 15)); + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif //PX_VEHICLE_WHEELS_H diff --git a/sources/PhysX/PhysX/source/fastxml/include/PsFastXml.h b/sources/PhysX/PhysX/source/fastxml/include/PsFastXml.h new file mode 100644 index 00000000..4e7ddcd9 --- /dev/null +++ b/sources/PhysX/PhysX/source/fastxml/include/PsFastXml.h @@ -0,0 +1,167 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFASTXML_PSFASTXML_H +#define PSFASTXML_PSFASTXML_H + +#include "foundation/PxSimpleTypes.h" // defines basic data types; modify for your platform as needed. +#include "foundation/PxIO.h" +#include "foundation/PxAssert.h" +#include "PsAllocator.h" + +namespace physx +{ +namespace shdfnd +{ + +class FastXml +{ + PX_NOCOPY(FastXml) + + public: + class AttributePairs + { + int argc; + const char** argv; + + public: + AttributePairs() : argc(0), argv(NULL) + { + } + AttributePairs(int c, const char** v) : argc(c), argv(v) + { + } + + PX_INLINE int getNbAttr() const + { + return argc / 2; + } + + const char* getKey(uint32_t index) const + { + PX_ASSERT((index * 2) < uint32_t(argc)); + return argv[index * 2]; + } + + const char* getValue(uint32_t index) const + { + PX_ASSERT((index * 2 + 1) < uint32_t(argc)); + return argv[index * 2 + 1]; + } + + const char* get(const char* attr) const + { + int32_t count = argc / 2; + for(int32_t i = 0; i < count; ++i) + { + const char* key = argv[i * 2], *value = argv[i * 2 + 1]; + if(strcmp(key, attr) == 0) + return value; + } + + return NULL; + } + }; + + /*** + * Callbacks to the user with the contents of the XML file properly digested. + */ + class Callback + { + public: + virtual ~Callback() + { + } + virtual bool processComment(const char* comment) = 0; // encountered a comment in the XML + + // 'element' is the name of the element that is being closed. + // depth is the recursion depth of this element. + // Return true to continue processing the XML file. + // Return false to stop processing the XML file; leaves the read pointer of the stream right after this close + // tag. + // The bool 'isError' indicates whether processing was stopped due to an error, or intentionally canceled early. + virtual bool processClose(const char* element, uint32_t depth, bool& isError) = 0; // process the 'close' + // indicator for a previously + // encountered element + + // return true to continue processing the XML document, false to skip. + virtual bool processElement(const char* elementName, // name of the element + const char* elementData, // element data, null if none + const AttributePairs& attr, // attributes + int32_t lineno) = 0; // line number in the source XML file + + // process the XML declaration header + virtual bool processXmlDeclaration(const AttributePairs&, // attributes + const char* /*elementData*/, int32_t /*lineno*/) + { + return true; + } + + virtual bool processDoctype(const char* /*rootElement*/, // Root element tag + const char* /*type*/, // SYSTEM or PUBLIC + const char* /*fpi*/, // Formal Public Identifier + const char* /*uri*/) // Path to schema file + { + return true; + } + + virtual void* allocate(uint32_t size) + { + return getAllocator().allocate(size, "FastXml", __FILE__, __LINE__); + } + + virtual void deallocate(void* ptr) + { + getAllocator().deallocate(ptr); + } + }; + + virtual bool processXml(PxInputData& buff, bool streamFromMemory = false) = 0; + + virtual const char* getError(int32_t& lineno) = 0; // report the reason for a parsing error, and the line number + // where it occurred. + + FastXml() + { + } + + virtual void release(void) = 0; + + protected: + virtual ~FastXml() + { + } +}; + +FastXml* createFastXml(FastXml::Callback* iface); + +} // shdfnd +} // physx + +#endif // PSFASTXML_PSFASTXML_H diff --git a/sources/PhysX/PhysX/source/foundation/include/Ps.h b/sources/PhysX/PhysX/source/foundation/include/Ps.h new file mode 100644 index 00000000..ca4c50d0 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/Ps.h @@ -0,0 +1,70 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PS_H +#define PSFOUNDATION_PS_H + +/*! \file top level include file for shared foundation */ + +#include "foundation/Px.h" + +/** +Platform specific defines +*/ +#if PX_WINDOWS_FAMILY || PX_XBOXONE +#pragma intrinsic(memcmp) +#pragma intrinsic(memcpy) +#pragma intrinsic(memset) +#pragma intrinsic(abs) +#pragma intrinsic(labs) +#endif + +// An expression that should expand to nothing in non PX_CHECKED builds. +// We currently use this only for tagging the purpose of containers for memory use tracking. +#if PX_CHECKED +#define PX_DEBUG_EXP(x) (x) +#else +#define PX_DEBUG_EXP(x) +#endif + +#define PX_SIGN_BITMASK 0x80000000 + +namespace physx +{ +namespace shdfnd +{ +// Int-as-bool type - has some uses for efficiency and with SIMD +typedef int IntBool; +static const IntBool IntFalse = 0; +static const IntBool IntTrue = 1; +} + +} // namespace physx + +#endif // #ifndef PSFOUNDATION_PS_H diff --git a/sources/PhysX/PhysX/source/foundation/include/PsAlignedMalloc.h b/sources/PhysX/PhysX/source/foundation/include/PsAlignedMalloc.h new file mode 100644 index 00000000..a7fdb2f2 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsAlignedMalloc.h @@ -0,0 +1,88 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSALIGNEDMALLOC_H +#define PSFOUNDATION_PSALIGNEDMALLOC_H + +#include "PsUserAllocated.h" + +/*! +Allocate aligned memory. +Alignment must be a power of 2! +-- should be templated by a base allocator +*/ + +namespace physx +{ +namespace shdfnd +{ +/** +Allocator, which is used to access the global PxAllocatorCallback instance +(used for dynamic data types template instantiation), which can align memory +*/ + +// SCS: AlignedMalloc with 3 params not found, seems not used on PC either +// disabled for now to avoid GCC error + +template +class AlignedAllocator : public BaseAllocator +{ + public: + AlignedAllocator(const BaseAllocator& base = BaseAllocator()) : BaseAllocator(base) + { + } + + void* allocate(size_t size, const char* file, int line) + { + size_t pad = N - 1 + sizeof(size_t); // store offset for delete. + uint8_t* base = reinterpret_cast(BaseAllocator::allocate(size + pad, file, line)); + if(!base) + return NULL; + + uint8_t* ptr = reinterpret_cast(size_t(base + pad) & ~(size_t(N) - 1)); // aligned pointer, ensuring N + // is a size_t + // wide mask + reinterpret_cast(ptr)[-1] = size_t(ptr - base); // store offset + + return ptr; + } + void deallocate(void* ptr) + { + if(ptr == NULL) + return; + + uint8_t* base = reinterpret_cast(ptr) - reinterpret_cast(ptr)[-1]; + BaseAllocator::deallocate(base); + } +}; + +} // namespace shdfnd +} // namespace physx + +#endif // #ifndef PSFOUNDATION_PSALIGNEDMALLOC_H diff --git a/sources/PhysX/PhysX/source/foundation/include/PsAlloca.h b/sources/PhysX/PhysX/source/foundation/include/PsAlloca.h new file mode 100644 index 00000000..cf331b82 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsAlloca.h @@ -0,0 +1,76 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSALLOCA_H +#define PSFOUNDATION_PSALLOCA_H + +#include "PsTempAllocator.h" + +namespace physx +{ +namespace shdfnd +{ +template +class ScopedPointer : private Alloc +{ + public: + ~ScopedPointer() + { + if(mOwned) + Alloc::deallocate(mPointer); + } + + operator T*() const + { + return mPointer; + } + + T* mPointer; + bool mOwned; +}; + +} // namespace shdfnd +} // namespace physx + +/*! Stack allocation for \c count instances of \c type. Falling back to temp allocator if using more than 1kB. */ +#ifdef __SPU__ +#define PX_ALLOCA(var, type, count) type* var = reinterpret_cast(PxAlloca(sizeof(type) * (count))) +#else +#define PX_ALLOCA(var, type, count) \ + physx::shdfnd::ScopedPointer var; \ + { \ + uint32_t size = sizeof(type) * (count); \ + var.mOwned = size > 1024; \ + if(var.mOwned) \ + var.mPointer = reinterpret_cast(physx::shdfnd::TempAllocator().allocate(size, __FILE__, __LINE__)); \ + else \ + var.mPointer = reinterpret_cast(PxAlloca(size)); \ + } +#endif +#endif // #ifndef PSFOUNDATION_PSALLOCA_H diff --git a/sources/PhysX/PhysX/source/foundation/include/PsAllocator.h b/sources/PhysX/PhysX/source/foundation/include/PsAllocator.h new file mode 100644 index 00000000..38b70fc3 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsAllocator.h @@ -0,0 +1,367 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSALLOCATOR_H +#define PSFOUNDATION_PSALLOCATOR_H + +#include "foundation/PxAllocatorCallback.h" +#include "foundation/PxAssert.h" +#include "PxFoundation.h" +#include "Ps.h" + +#if(PX_WINDOWS_FAMILY || PX_XBOXONE) + #include + #include +#endif +#if(PX_APPLE_FAMILY) + #include +#endif + +#include + +// Allocation macros going through user allocator +#if PX_CHECKED + #define PX_ALLOC(n, name) physx::shdfnd::NamedAllocator(name).allocate(n, __FILE__, __LINE__) +#else + #define PX_ALLOC(n, name) physx::shdfnd::NonTrackingAllocator().allocate(n, __FILE__, __LINE__) +#endif +#define PX_ALLOC_TEMP(n, name) PX_ALLOC(n, name) +#define PX_FREE(x) physx::shdfnd::NonTrackingAllocator().deallocate(x) +#define PX_FREE_AND_RESET(x) \ + { \ + PX_FREE(x); \ + x = 0; \ + } + +// The following macros support plain-old-types and classes derived from UserAllocated. +#define PX_NEW(T) new (physx::shdfnd::ReflectionAllocator(), __FILE__, __LINE__) T +#define PX_NEW_TEMP(T) PX_NEW(T) +#define PX_DELETE(x) delete x +#define PX_DELETE_AND_RESET(x) \ + { \ + PX_DELETE(x); \ + x = 0; \ + } +#define PX_DELETE_POD(x) \ + { \ + PX_FREE(x); \ + x = 0; \ + } +#define PX_DELETE_ARRAY(x) \ + { \ + PX_DELETE([] x); \ + x = 0; \ + } + +// aligned allocation +#define PX_ALIGNED16_ALLOC(n) physx::shdfnd::AlignedAllocator<16>().allocate(n, __FILE__, __LINE__) +#define PX_ALIGNED16_FREE(x) physx::shdfnd::AlignedAllocator<16>().deallocate(x) + +//! placement new macro to make it easy to spot bad use of 'new' +#define PX_PLACEMENT_NEW(p, T) new (p) T + +#if PX_DEBUG || PX_CHECKED + #define PX_USE_NAMED_ALLOCATOR 1 +#else + #define PX_USE_NAMED_ALLOCATOR 0 +#endif + +// Don't use inline for alloca !!! +#if PX_WINDOWS_FAMILY + #include + #define PxAlloca(x) _alloca(x) +#elif PX_LINUX || PX_ANDROID + #include + #define PxAlloca(x) alloca(x) +#elif PX_APPLE_FAMILY + #include + #define PxAlloca(x) alloca(x) +#elif PX_PS4 + #include + #define PxAlloca(x) alloca(x) +#elif PX_XBOXONE + #include + #define PxAlloca(x) alloca(x) +#elif PX_SWITCH + #include + #define PxAlloca(x) alloca(x) +#endif + +#define PxAllocaAligned(x, alignment) ((size_t(PxAlloca(x + alignment)) + (alignment - 1)) & ~size_t(alignment - 1)) + +namespace physx +{ +namespace shdfnd +{ + +PX_FOUNDATION_API PxAllocatorCallback& getAllocator(); + +/** +Allocator used to access the global PxAllocatorCallback instance without providing additional information. +*/ + +class PX_FOUNDATION_API Allocator +{ + public: + Allocator(const char* = 0) + { + } + void* allocate(size_t size, const char* file, int line); + void deallocate(void* ptr); +}; + +/* + * Bootstrap allocator using malloc/free. + * Don't use unless your objects get allocated before foundation is initialized. + */ +class RawAllocator +{ + public: + RawAllocator(const char* = 0) + { + } + void* allocate(size_t size, const char*, int) + { + // malloc returns valid pointer for size==0, no need to check + return ::malloc(size); + } + void deallocate(void* ptr) + { + // free(0) is guaranteed to have no side effect, no need to check + ::free(ptr); + } +}; + +/* + * Allocator that simply calls straight back to the application without tracking. + * This is used by the heap (Foundation::mNamedAllocMap) that tracks allocations + * because it needs to be able to grow as a result of an allocation. + * Making the hash table re-entrant to deal with this may not make sense. + */ +class NonTrackingAllocator +{ + public: + PX_FORCE_INLINE NonTrackingAllocator(const char* = 0) + { + } + PX_FORCE_INLINE void* allocate(size_t size, const char* file, int line) + { + return !size ? 0 : getAllocator().allocate(size, "NonTrackedAlloc", file, line); + } + PX_FORCE_INLINE void deallocate(void* ptr) + { + if(ptr) + getAllocator().deallocate(ptr); + } +}; + +/* +\brief Virtual allocator callback used to provide run-time defined allocators to foundation types like Array or Bitmap. + This is used by VirtualAllocator +*/ +class VirtualAllocatorCallback +{ + public: + VirtualAllocatorCallback() + { + } + virtual ~VirtualAllocatorCallback() + { + } + virtual void* allocate(const size_t size, const char* file, const int line) = 0; + virtual void deallocate(void* ptr) = 0; +}; + +/* +\brief Virtual allocator to be used by foundation types to provide run-time defined allocators. +Due to the fact that Array extends its allocator, rather than contains a reference/pointer to it, the VirtualAllocator +must +be a concrete type containing a pointer to a virtual callback. The callback may not be available at instantiation time, +therefore +methods are provided to set the callback later. +*/ +class VirtualAllocator +{ + public: + VirtualAllocator(VirtualAllocatorCallback* callback = NULL) : mCallback(callback) + { + } + + void* allocate(const size_t size, const char* file, const int line) + { + PX_ASSERT(mCallback); + if(size) + return mCallback->allocate(size, file, line); + return NULL; + } + void deallocate(void* ptr) + { + PX_ASSERT(mCallback); + if(ptr) + mCallback->deallocate(ptr); + } + + void setCallback(VirtualAllocatorCallback* callback) + { + mCallback = callback; + } + VirtualAllocatorCallback* getCallback() + { + return mCallback; + } + + private: + VirtualAllocatorCallback* mCallback; + VirtualAllocator& operator=(const VirtualAllocator&); +}; + +#if PX_USE_NAMED_ALLOCATOR // can be slow, so only use in debug/checked +class PX_FOUNDATION_API NamedAllocator +{ + public: + NamedAllocator(const PxEMPTY); + NamedAllocator(const char* name = 0); // todo: should not have default argument! + NamedAllocator(const NamedAllocator&); + ~NamedAllocator(); + NamedAllocator& operator=(const NamedAllocator&); + void* allocate(size_t size, const char* filename, int line); + void deallocate(void* ptr); +}; +#else +class NamedAllocator; +#endif // PX_DEBUG + +/** +Allocator used to access the global PxAllocatorCallback instance using a static name derived from T. +*/ + +template +class ReflectionAllocator +{ + static const char* getName() + { + if(!PxGetFoundation().getReportAllocationNames()) + return ""; +#if PX_GCC_FAMILY + return __PRETTY_FUNCTION__; +#else + // name() calls malloc(), raw_name() wouldn't + return typeid(T).name(); +#endif + } + + public: + ReflectionAllocator(const PxEMPTY) + { + } + ReflectionAllocator(const char* = 0) + { + } + inline ReflectionAllocator(const ReflectionAllocator&) + { + } + void* allocate(size_t size, const char* filename, int line) + { + return size ? getAllocator().allocate(size, getName(), filename, line) : 0; + } + void deallocate(void* ptr) + { + if(ptr) + getAllocator().deallocate(ptr); + } +}; + +template +struct AllocatorTraits +{ +#if PX_USE_NAMED_ALLOCATOR + typedef NamedAllocator Type; +#else + typedef ReflectionAllocator Type; +#endif +}; + +// if you get a build error here, you are trying to PX_NEW a class +// that is neither plain-old-type nor derived from UserAllocated +template +union EnableIfPod +{ + int i; + T t; + typedef X Type; +}; + +} // namespace shdfnd +} // namespace physx + +// Global placement new for ReflectionAllocator templated by +// plain-old-type. Allows using PX_NEW for pointers and built-in-types. +// +// ATTENTION: You need to use PX_DELETE_POD or PX_FREE to deallocate +// memory, not PX_DELETE. PX_DELETE_POD redirects to PX_FREE. +// +// Rationale: PX_DELETE uses global operator delete(void*), which we dont' want to overload. +// Any other definition of PX_DELETE couldn't support array syntax 'PX_DELETE([]a);'. +// PX_DELETE_POD was preferred over PX_DELETE_ARRAY because it is used +// less often and applies to both single instances and arrays. +template +PX_INLINE void* operator new(size_t size, physx::shdfnd::ReflectionAllocator alloc, const char* fileName, + typename physx::shdfnd::EnableIfPod::Type line) +{ + return alloc.allocate(size, fileName, line); +} + +template +PX_INLINE void* operator new [](size_t size, physx::shdfnd::ReflectionAllocator alloc, const char* fileName, + typename physx::shdfnd::EnableIfPod::Type line) +{ return alloc.allocate(size, fileName, line); } + +// If construction after placement new throws, this placement delete is being called. +template +PX_INLINE void operator delete(void* ptr, physx::shdfnd::ReflectionAllocator alloc, const char* fileName, + typename physx::shdfnd::EnableIfPod::Type line) +{ + PX_UNUSED(fileName); + PX_UNUSED(line); + + alloc.deallocate(ptr); +} + +// If construction after placement new throws, this placement delete is being called. +template +PX_INLINE void operator delete [](void* ptr, physx::shdfnd::ReflectionAllocator alloc, const char* fileName, + typename physx::shdfnd::EnableIfPod::Type line) +{ + PX_UNUSED(fileName); + PX_UNUSED(line); + + alloc.deallocate(ptr); +} + +#endif // #ifndef PSFOUNDATION_PSALLOCATOR_H diff --git a/sources/PhysX/PhysX/source/foundation/include/PsAoS.h b/sources/PhysX/PhysX/source/foundation/include/PsAoS.h new file mode 100644 index 00000000..ff7d0848 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsAoS.h @@ -0,0 +1,45 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSAOS_H +#define PSFOUNDATION_PSAOS_H + +#include "foundation/Px.h" + +#if PX_WINDOWS && !PX_NEON +#include "windows/PsWindowsAoS.h" +#elif(PX_UNIX_FAMILY || PX_PS4 || PX_SWITCH || (PX_UWP && PX_NEON)) +#include "unix/PsUnixAoS.h" +#elif PX_XBOXONE +#include "XboxOne/PsXboxOneAoS.h" +#else +#error "Platform not supported!" +#endif + +#endif diff --git a/sources/PhysX/PhysX/source/foundation/include/PsArray.h b/sources/PhysX/PhysX/source/foundation/include/PsArray.h new file mode 100644 index 00000000..96f44bbd --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsArray.h @@ -0,0 +1,721 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSARRAY_H +#define PSFOUNDATION_PSARRAY_H + +#include "foundation/PxAssert.h" +#include "foundation/PxIntrinsics.h" +#include "PsAllocator.h" +#include "PsBasicTemplates.h" + +namespace physx +{ +namespace shdfnd +{ +template +void exportArray(Serializer& stream, const void* data, uint32_t size, uint32_t sizeOfElement, uint32_t capacity); +char* importArray(char* address, void** data, uint32_t size, uint32_t sizeOfElement, uint32_t capacity); + +/*! +An array is a sequential container. + +Implementation note +* entries between 0 and size are valid objects +* we use inheritance to build this because the array is included inline in a lot + of objects and we want the allocator to take no space if it's not stateful, which + aggregation doesn't allow. Also, we want the metadata at the front for the inline + case where the allocator contains some inline storage space +*/ +template ::Type> +class Array : protected Alloc +{ + public: + typedef T* Iterator; + typedef const T* ConstIterator; + + explicit Array(const PxEMPTY v) : Alloc(v) + { + if(mData) + mCapacity |= PX_SIGN_BITMASK; + } + + /*! + Default array constructor. Initialize an empty array + */ + PX_INLINE explicit Array(const Alloc& alloc = Alloc()) : Alloc(alloc), mData(0), mSize(0), mCapacity(0) + { + } + + /*! + Initialize array with given capacity + */ + PX_INLINE explicit Array(uint32_t size, const T& a = T(), const Alloc& alloc = Alloc()) + : Alloc(alloc), mData(0), mSize(0), mCapacity(0) + { + resize(size, a); + } + + /*! + Copy-constructor. Copy all entries from other array + */ + template + PX_INLINE explicit Array(const Array& other, const Alloc& alloc = Alloc()) + : Alloc(alloc) + { + copy(other); + } + + // This is necessary else the basic default copy constructor is used in the case of both arrays being of the same + // template instance + // The C++ standard clearly states that a template constructor is never a copy constructor [2]. In other words, + // the presence of a template constructor does not suppress the implicit declaration of the copy constructor. + // Also never make a copy constructor explicit, or copy-initialization* will no longer work. This is because + // 'binding an rvalue to a const reference requires an accessible copy constructor' (http://gcc.gnu.org/bugs/) + // *http://stackoverflow.com/questions/1051379/is-there-a-difference-in-c-between-copy-initialization-and-assignment-initializ + PX_INLINE Array(const Array& other, const Alloc& alloc = Alloc()) : Alloc(alloc) + { + copy(other); + } + + /*! + Initialize array with given length + */ + PX_INLINE explicit Array(const T* first, const T* last, const Alloc& alloc = Alloc()) + : Alloc(alloc), mSize(last < first ? 0 : uint32_t(last - first)), mCapacity(mSize) + { + mData = allocate(mSize); + copy(mData, mData + mSize, first); + } + + /*! + Destructor + */ + PX_INLINE ~Array() + { + destroy(mData, mData + mSize); + + if(capacity() && !isInUserMemory()) + deallocate(mData); + } + + /*! + Assignment operator. Copy content (deep-copy) + */ + template + PX_INLINE Array& operator=(const Array& rhs) + { + if(&rhs == this) + return *this; + + clear(); + reserve(rhs.mSize); + copy(mData, mData + rhs.mSize, rhs.mData); + + mSize = rhs.mSize; + return *this; + } + + PX_INLINE Array& operator=(const Array& t) // Needs to be declared, see comment at copy-constructor + { + return operator=(t); + } + + /*! + Array indexing operator. + \param i + The index of the element that will be returned. + \return + The element i in the array. + */ + PX_FORCE_INLINE const T& operator[](uint32_t i) const + { + PX_ASSERT(i < mSize); + return mData[i]; + } + + /*! + Array indexing operator. + \param i + The index of the element that will be returned. + \return + The element i in the array. + */ + PX_FORCE_INLINE T& operator[](uint32_t i) + { + PX_ASSERT(i < mSize); + return mData[i]; + } + + /*! + Returns a pointer to the initial element of the array. + \return + a pointer to the initial element of the array. + */ + PX_FORCE_INLINE ConstIterator begin() const + { + return mData; + } + + PX_FORCE_INLINE Iterator begin() + { + return mData; + } + + /*! + Returns an iterator beyond the last element of the array. Do not dereference. + \return + a pointer to the element beyond the last element of the array. + */ + + PX_FORCE_INLINE ConstIterator end() const + { + return mData + mSize; + } + + PX_FORCE_INLINE Iterator end() + { + return mData + mSize; + } + + /*! + Returns a reference to the first element of the array. Undefined if the array is empty. + \return a reference to the first element of the array + */ + + PX_FORCE_INLINE const T& front() const + { + PX_ASSERT(mSize); + return mData[0]; + } + + PX_FORCE_INLINE T& front() + { + PX_ASSERT(mSize); + return mData[0]; + } + + /*! + Returns a reference to the last element of the array. Undefined if the array is empty + \return a reference to the last element of the array + */ + + PX_FORCE_INLINE const T& back() const + { + PX_ASSERT(mSize); + return mData[mSize - 1]; + } + + PX_FORCE_INLINE T& back() + { + PX_ASSERT(mSize); + return mData[mSize - 1]; + } + + /*! + Returns the number of entries in the array. This can, and probably will, + differ from the array capacity. + \return + The number of of entries in the array. + */ + PX_FORCE_INLINE uint32_t size() const + { + return mSize; + } + + /*! + Clears the array. + */ + PX_INLINE void clear() + { + destroy(mData, mData + mSize); + mSize = 0; + } + + /*! + Returns whether the array is empty (i.e. whether its size is 0). + \return + true if the array is empty + */ + PX_FORCE_INLINE bool empty() const + { + return mSize == 0; + } + + /*! + Finds the first occurrence of an element in the array. + \param a + The element to find. + */ + + PX_INLINE Iterator find(const T& a) + { + uint32_t index; + for(index = 0; index < mSize && mData[index] != a; index++) + ; + return mData + index; + } + + PX_INLINE ConstIterator find(const T& a) const + { + uint32_t index; + for(index = 0; index < mSize && mData[index] != a; index++) + ; + return mData + index; + } + + ///////////////////////////////////////////////////////////////////////// + /*! + Adds one element to the end of the array. Operation is O(1). + \param a + The element that will be added to this array. + */ + ///////////////////////////////////////////////////////////////////////// + + PX_FORCE_INLINE T& pushBack(const T& a) + { + if(capacity() <= mSize) + return growAndPushBack(a); + + PX_PLACEMENT_NEW(reinterpret_cast(mData + mSize), T)(a); + + return mData[mSize++]; + } + + ///////////////////////////////////////////////////////////////////////// + /*! + Returns the element at the end of the array. Only legal if the array is non-empty. + */ + ///////////////////////////////////////////////////////////////////////// + PX_INLINE T popBack() + { + PX_ASSERT(mSize); + T t = mData[mSize - 1]; + + mData[--mSize].~T(); + + return t; + } + + ///////////////////////////////////////////////////////////////////////// + /*! + Construct one element at the end of the array. Operation is O(1). + */ + ///////////////////////////////////////////////////////////////////////// + PX_INLINE T& insert() + { + if(capacity() <= mSize) + grow(capacityIncrement()); + + T* ptr = mData + mSize++; + new (ptr) T; // not 'T()' because PODs should not get default-initialized. + return *ptr; + } + + ///////////////////////////////////////////////////////////////////////// + /*! + Subtracts the element on position i from the array and replace it with + the last element. + Operation is O(1) + \param i + The position of the element that will be subtracted from this array. + */ + ///////////////////////////////////////////////////////////////////////// + PX_INLINE void replaceWithLast(uint32_t i) + { + PX_ASSERT(i < mSize); + mData[i] = mData[--mSize]; + + mData[mSize].~T(); + } + + PX_INLINE void replaceWithLast(Iterator i) + { + replaceWithLast(static_cast(i - mData)); + } + + ///////////////////////////////////////////////////////////////////////// + /*! + Replaces the first occurrence of the element a with the last element + Operation is O(n) + \param a + The position of the element that will be subtracted from this array. + \return true if the element has been removed. + */ + ///////////////////////////////////////////////////////////////////////// + + PX_INLINE bool findAndReplaceWithLast(const T& a) + { + uint32_t index = 0; + while(index < mSize && mData[index] != a) + ++index; + if(index == mSize) + return false; + replaceWithLast(index); + return true; + } + + ///////////////////////////////////////////////////////////////////////// + /*! + Subtracts the element on position i from the array. Shift the entire + array one step. + Operation is O(n) + \param i + The position of the element that will be subtracted from this array. + */ + ///////////////////////////////////////////////////////////////////////// + PX_INLINE void remove(uint32_t i) + { + PX_ASSERT(i < mSize); + + T* it = mData + i; + it->~T(); + while (++i < mSize) + { + new (it) T(mData[i]); + ++it; + it->~T(); + } + --mSize; + } + + ///////////////////////////////////////////////////////////////////////// + /*! + Removes a range from the array. Shifts the array so order is maintained. + Operation is O(n) + \param begin + The starting position of the element that will be subtracted from this array. + \param count + The number of elments that will be subtracted from this array. + */ + ///////////////////////////////////////////////////////////////////////// + PX_INLINE void removeRange(uint32_t begin, uint32_t count) + { + PX_ASSERT(begin < mSize); + PX_ASSERT((begin + count) <= mSize); + + for(uint32_t i = 0; i < count; i++) + mData[begin + i].~T(); // call the destructor on the ones being removed first. + + T* dest = &mData[begin]; // location we are copying the tail end objects to + T* src = &mData[begin + count]; // start of tail objects + uint32_t move_count = mSize - (begin + count); // compute remainder that needs to be copied down + + for(uint32_t i = 0; i < move_count; i++) + { + new (dest) T(*src); // copy the old one to the new location + src->~T(); // call the destructor on the old location + dest++; + src++; + } + mSize -= count; + } + + ////////////////////////////////////////////////////////////////////////// + /*! + Resize array + */ + ////////////////////////////////////////////////////////////////////////// + PX_NOINLINE void resize(const uint32_t size, const T& a = T()); + + PX_NOINLINE void resizeUninitialized(const uint32_t size); + + ////////////////////////////////////////////////////////////////////////// + /*! + Resize array such that only as much memory is allocated to hold the + existing elements + */ + ////////////////////////////////////////////////////////////////////////// + PX_INLINE void shrink() + { + recreate(mSize); + } + + ////////////////////////////////////////////////////////////////////////// + /*! + Deletes all array elements and frees memory. + */ + ////////////////////////////////////////////////////////////////////////// + PX_INLINE void reset() + { + resize(0); + shrink(); + } + + ////////////////////////////////////////////////////////////////////////// + /*! + Ensure that the array has at least size capacity. + */ + ////////////////////////////////////////////////////////////////////////// + PX_INLINE void reserve(const uint32_t capacity) + { + if(capacity > this->capacity()) + grow(capacity); + } + + ////////////////////////////////////////////////////////////////////////// + /*! + Query the capacity(allocated mem) for the array. + */ + ////////////////////////////////////////////////////////////////////////// + PX_FORCE_INLINE uint32_t capacity() const + { + return mCapacity & ~PX_SIGN_BITMASK; + } + + ////////////////////////////////////////////////////////////////////////// + /*! + Unsafe function to force the size of the array + */ + ////////////////////////////////////////////////////////////////////////// + PX_FORCE_INLINE void forceSize_Unsafe(uint32_t size) + { + PX_ASSERT(size <= mCapacity); + mSize = size; + } + + ////////////////////////////////////////////////////////////////////////// + /*! + Swap contents of an array without allocating temporary storage + */ + ////////////////////////////////////////////////////////////////////////// + PX_INLINE void swap(Array& other) + { + shdfnd::swap(mData, other.mData); + shdfnd::swap(mSize, other.mSize); + shdfnd::swap(mCapacity, other.mCapacity); + } + + ////////////////////////////////////////////////////////////////////////// + /*! + Assign a range of values to this vector (resizes to length of range) + */ + ////////////////////////////////////////////////////////////////////////// + PX_INLINE void assign(const T* first, const T* last) + { + resizeUninitialized(uint32_t(last - first)); + copy(begin(), end(), first); + } + + // We need one bit to mark arrays that have been deserialized from a user-provided memory block. + // For alignment & memory saving purpose we store that bit in the rarely used capacity member. + PX_FORCE_INLINE uint32_t isInUserMemory() const + { + return mCapacity & PX_SIGN_BITMASK; + } + + /// return reference to allocator + PX_INLINE Alloc& getAllocator() + { + return *this; + } + + protected: + // constructor for where we don't own the memory + Array(T* memory, uint32_t size, uint32_t capacity, const Alloc& alloc = Alloc()) + : Alloc(alloc), mData(memory), mSize(size), mCapacity(capacity | PX_SIGN_BITMASK) + { + } + + template + PX_NOINLINE void copy(const Array& other); + + PX_INLINE T* allocate(uint32_t size) + { + if(size > 0) + { + T* p = reinterpret_cast(Alloc::allocate(sizeof(T) * size, __FILE__, __LINE__)); +/** +Mark a specified amount of memory with 0xcd pattern. This is used to check that the meta data +definition for serialized classes is complete in checked builds. +*/ +#if PX_CHECKED + if(p) + { + for(uint32_t i = 0; i < (sizeof(T) * size); ++i) + reinterpret_cast(p)[i] = 0xcd; + } +#endif + return p; + } + return 0; + } + + PX_INLINE void deallocate(void* mem) + { + Alloc::deallocate(mem); + } + + static PX_INLINE void create(T* first, T* last, const T& a) + { + for(; first < last; ++first) + ::new (first) T(a); + } + + static PX_INLINE void copy(T* first, T* last, const T* src) + { + if(last <= first) + return; + + for(; first < last; ++first, ++src) + ::new (first) T(*src); + } + + static PX_INLINE void destroy(T* first, T* last) + { + for(; first < last; ++first) + first->~T(); + } + + /*! + Called when pushBack() needs to grow the array. + \param a The element that will be added to this array. + */ + PX_NOINLINE T& growAndPushBack(const T& a); + + /*! + Resizes the available memory for the array. + + \param capacity + The number of entries that the set should be able to hold. + */ + PX_INLINE void grow(uint32_t capacity) + { + PX_ASSERT(this->capacity() < capacity); + recreate(capacity); + } + + /*! + Creates a new memory block, copies all entries to the new block and destroys old entries. + + \param capacity + The number of entries that the set should be able to hold. + */ + PX_NOINLINE void recreate(uint32_t capacity); + + // The idea here is to prevent accidental bugs with pushBack or insert. Unfortunately + // it interacts badly with InlineArrays with smaller inline allocations. + // TODO(dsequeira): policy template arg, this is exactly what they're for. + PX_INLINE uint32_t capacityIncrement() const + { + const uint32_t capacity = this->capacity(); + return capacity == 0 ? 1 : capacity * 2; + } + + T* mData; + uint32_t mSize; + uint32_t mCapacity; +}; + +template +PX_NOINLINE void Array::resize(const uint32_t size, const T& a) +{ + reserve(size); + create(mData + mSize, mData + size, a); + destroy(mData + size, mData + mSize); + mSize = size; +} + +template +template +PX_NOINLINE void Array::copy(const Array& other) +{ + if(!other.empty()) + { + mData = allocate(mSize = mCapacity = other.size()); + copy(mData, mData + mSize, other.begin()); + } + else + { + mData = NULL; + mSize = 0; + mCapacity = 0; + } + + // mData = allocate(other.mSize); + // mSize = other.mSize; + // mCapacity = other.mSize; + // copy(mData, mData + mSize, other.mData); +} + +template +PX_NOINLINE void Array::resizeUninitialized(const uint32_t size) +{ + reserve(size); + mSize = size; +} + +template +PX_NOINLINE T& Array::growAndPushBack(const T& a) +{ + uint32_t capacity = capacityIncrement(); + + T* newData = allocate(capacity); + PX_ASSERT((!capacity) || (newData && (newData != mData))); + copy(newData, newData + mSize, mData); + + // inserting element before destroying old array + // avoids referencing destroyed object when duplicating array element. + PX_PLACEMENT_NEW(reinterpret_cast(newData + mSize), T)(a); + + destroy(mData, mData + mSize); + if(!isInUserMemory()) + deallocate(mData); + + mData = newData; + mCapacity = capacity; + + return mData[mSize++]; +} + +template +PX_NOINLINE void Array::recreate(uint32_t capacity) +{ + T* newData = allocate(capacity); + PX_ASSERT((!capacity) || (newData && (newData != mData))); + + copy(newData, newData + mSize, mData); + destroy(mData, mData + mSize); + if(!isInUserMemory()) + deallocate(mData); + + mData = newData; + mCapacity = capacity; +} + +template +PX_INLINE void swap(Array& x, Array& y) +{ + x.swap(y); +} + +} // namespace shdfnd +} // namespace physx + +#endif // #ifndef PSFOUNDATION_PSARRAY_H diff --git a/sources/PhysX/PhysX/source/foundation/include/PsAtomic.h b/sources/PhysX/PhysX/source/foundation/include/PsAtomic.h new file mode 100644 index 00000000..7d32dc92 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsAtomic.h @@ -0,0 +1,64 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSATOMIC_H +#define PSFOUNDATION_PSATOMIC_H + +#include "Ps.h" +#include "foundation/PxFoundationConfig.h" + +namespace physx +{ +namespace shdfnd +{ +/* set *dest equal to val. Return the old value of *dest */ +PX_FOUNDATION_API int32_t atomicExchange(volatile int32_t* dest, int32_t val); + +/* if *dest == comp, replace with exch. Return original value of *dest */ +PX_FOUNDATION_API int32_t atomicCompareExchange(volatile int32_t* dest, int32_t exch, int32_t comp); + +/* if *dest == comp, replace with exch. Return original value of *dest */ +PX_FOUNDATION_API void* atomicCompareExchangePointer(volatile void** dest, void* exch, void* comp); + +/* increment the specified location. Return the incremented value */ +PX_FOUNDATION_API int32_t atomicIncrement(volatile int32_t* val); + +/* decrement the specified location. Return the decremented value */ +PX_FOUNDATION_API int32_t atomicDecrement(volatile int32_t* val); + +/* add delta to *val. Return the new value */ +PX_FOUNDATION_API int32_t atomicAdd(volatile int32_t* val, int32_t delta); + +/* compute the maximum of dest and val. Return the new value */ +PX_FOUNDATION_API int32_t atomicMax(volatile int32_t* val, int32_t val2); + +} // namespace shdfnd +} // namespace physx + +#endif // #ifndef PSFOUNDATION_PSATOMIC_H diff --git a/sources/PhysX/PhysX/source/foundation/include/PsBasicTemplates.h b/sources/PhysX/PhysX/source/foundation/include/PsBasicTemplates.h new file mode 100644 index 00000000..5ec03594 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsBasicTemplates.h @@ -0,0 +1,146 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSBASICTEMPLATES_H +#define PSFOUNDATION_PSBASICTEMPLATES_H + +#include "Ps.h" + +namespace physx +{ +namespace shdfnd +{ +template +struct Equal +{ + bool operator()(const A& a, const A& b) const + { + return a == b; + } +}; + +template +struct Less +{ + bool operator()(const A& a, const A& b) const + { + return a < b; + } +}; + +template +struct Greater +{ + bool operator()(const A& a, const A& b) const + { + return a > b; + } +}; + +template +class Pair +{ + public: + F first; + S second; + Pair() : first(F()), second(S()) + { + } + Pair(const F& f, const S& s) : first(f), second(s) + { + } + Pair(const Pair& p) : first(p.first), second(p.second) + { + } + // CN - fix for /.../PsBasicTemplates.h(61) : warning C4512: 'physx::shdfnd::Pair' : assignment operator could + // not be generated + Pair& operator=(const Pair& p) + { + first = p.first; + second = p.second; + return *this; + } + bool operator==(const Pair& p) const + { + return first == p.first && second == p.second; + } + bool operator<(const Pair& p) const + { + if(first < p.first) + return true; + else + return !(p.first < first) && (second < p.second); + } +}; + +template +struct LogTwo +{ + static const unsigned int value = LogTwo<(A >> 1)>::value + 1; +}; +template <> +struct LogTwo<1> +{ + static const unsigned int value = 0; +}; + +template +struct UnConst +{ + typedef T Type; +}; +template +struct UnConst +{ + typedef T Type; +}; + +template +T pointerOffset(void* p, ptrdiff_t offset) +{ + return reinterpret_cast(reinterpret_cast(p) + offset); +} +template +T pointerOffset(const void* p, ptrdiff_t offset) +{ + return reinterpret_cast(reinterpret_cast(p) + offset); +} + +template +PX_CUDA_CALLABLE PX_INLINE void swap(T& x, T& y) +{ + const T tmp = x; + x = y; + y = tmp; +} + +} // namespace shdfnd +} // namespace physx + +#endif // #ifndef PSFOUNDATION_PSBASICTEMPLATES_H diff --git a/sources/PhysX/PhysX/source/foundation/include/PsBitUtils.h b/sources/PhysX/PhysX/source/foundation/include/PsBitUtils.h new file mode 100644 index 00000000..288abe69 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsBitUtils.h @@ -0,0 +1,109 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSBITUTILS_H +#define PSFOUNDATION_PSBITUTILS_H + +#include "foundation/PxIntrinsics.h" +#include "foundation/PxAssert.h" +#include "PsIntrinsics.h" +#include "Ps.h" + +namespace physx +{ +namespace shdfnd +{ +PX_INLINE uint32_t bitCount(uint32_t v) +{ + // from http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel + uint32_t const w = v - ((v >> 1) & 0x55555555); + uint32_t const x = (w & 0x33333333) + ((w >> 2) & 0x33333333); + return (((x + (x >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24; +} + +PX_INLINE bool isPowerOfTwo(uint32_t x) +{ + return x != 0 && (x & (x - 1)) == 0; +} + +// "Next Largest Power of 2 +// Given a binary integer value x, the next largest power of 2 can be computed by a SWAR algorithm +// that recursively "folds" the upper bits into the lower bits. This process yields a bit vector with +// the same most significant 1 as x, but all 1's below it. Adding 1 to that value yields the next +// largest power of 2. For a 32-bit value:" +PX_INLINE uint32_t nextPowerOfTwo(uint32_t x) +{ + x |= (x >> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); + return x + 1; +} + +/*! +Return the index of the highest set bit. Not valid for zero arg. +*/ + +PX_INLINE uint32_t lowestSetBit(uint32_t x) +{ + PX_ASSERT(x); + return lowestSetBitUnsafe(x); +} + +/*! +Return the index of the highest set bit. Not valid for zero arg. +*/ + +PX_INLINE uint32_t highestSetBit(uint32_t x) +{ + PX_ASSERT(x); + return highestSetBitUnsafe(x); +} + +// Helper function to approximate log2 of an integer value +// assumes that the input is actually power of two. +// todo: replace 2 usages with 'highestSetBit' +PX_INLINE uint32_t ilog2(uint32_t num) +{ + for(uint32_t i = 0; i < 32; i++) + { + num >>= 1; + if(num == 0) + return i; + } + + PX_ASSERT(0); + return uint32_t(-1); +} + +} // namespace shdfnd +} // namespace physx + +#endif // #ifndef PSFOUNDATION_PSBITUTILS_H diff --git a/sources/PhysX/PhysX/source/foundation/include/PsBroadcast.h b/sources/PhysX/PhysX/source/foundation/include/PsBroadcast.h new file mode 100644 index 00000000..e0d9d36e --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsBroadcast.h @@ -0,0 +1,277 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSBROADCAST_H +#define PSFOUNDATION_PSBROADCAST_H + +#include "Ps.h" +#include "PsInlineArray.h" + +#include "foundation/PxSimpleTypes.h" +#include "foundation/PxErrorCallback.h" + +namespace physx +{ +namespace shdfnd +{ + +/** +\brief Abstract listener class that listens to allocation and deallocation events from the + foundation memory system. + +Threading: All methods of this class should be thread safe as it can be called from the user thread +or the physics processing thread(s). +*/ +class AllocationListener +{ + public: + /** + \brief callback when memory is allocated. + \param size Size of the allocation in bytes. + \param typeName Type this data is being allocated for. + \param filename File the allocation came from. + \param line the allocation came from. + \param allocatedMemory memory that will be returned from the allocation. + */ + virtual void onAllocation(size_t size, const char* typeName, const char* filename, int line, + void* allocatedMemory) = 0; + + /** + \brief callback when memory is deallocated. + \param allocatedMemory memory just before allocation. + */ + virtual void onDeallocation(void* allocatedMemory) = 0; + + protected: + virtual ~AllocationListener() + { + } +}; + +/** +\brief Broadcast class implementation, registering listeners. + +Threading: All methods of this class should be thread safe as it can be called from the user thread +or the physics processing thread(s). There is not internal locking +*/ +template +class Broadcast : public Base +{ + public: + static const uint32_t MAX_NB_LISTENERS = 16; + + /** + \brief The default constructor. + */ + Broadcast() + { + } + + /** + \brief Register new listener. + + \note It is NOT SAFE to register and deregister listeners while allocations may be taking place. + moreover, there is no thread safety to registration/deregistration. + + \param listener Listener to register. + */ + void registerListener(Listener& listener) + { + if(mListeners.size() < MAX_NB_LISTENERS) + mListeners.pushBack(&listener); + } + + /** + \brief Deregister an existing listener. + + \note It is NOT SAFE to register and deregister listeners while allocations may be taking place. + moreover, there is no thread safety to registration/deregistration. + + \param listener Listener to deregister. + */ + void deregisterListener(Listener& listener) + { + mListeners.findAndReplaceWithLast(&listener); + } + + /** + \brief Get number of registered listeners. + + \return Number of listeners. + */ + uint32_t getNbListeners() const + { + return mListeners.size(); + } + + /** + \brief Get an existing listener from given index. + + \param index Index of the listener. + \return Listener on given index. + */ + Listener& getListener(uint32_t index) + { + PX_ASSERT(index <= mListeners.size()); + return *mListeners[index]; + } + + protected: + virtual ~Broadcast() + { + } + + physx::shdfnd::InlineArray mListeners; +}; + +/** +\brief Abstract base class for an application defined memory allocator that allows an external listener +to audit the memory allocations. +*/ +class BroadcastingAllocator : public Broadcast +{ + PX_NOCOPY(BroadcastingAllocator) + + public: + /** + \brief The default constructor. + */ + BroadcastingAllocator(PxAllocatorCallback& allocator, PxErrorCallback& error) : mAllocator(allocator), mError(error) + { + mListeners.clear(); + } + + /** + \brief The default constructor. + */ + virtual ~BroadcastingAllocator() + { + mListeners.clear(); + } + + /** + \brief Allocates size bytes of memory, which must be 16-byte aligned. + + This method should never return NULL. If you run out of memory, then + you should terminate the app or take some other appropriate action. + + Threading: This function should be thread safe as it can be called in the context of the user thread + and physics processing thread(s). + + \param size Number of bytes to allocate. + \param typeName Name of the datatype that is being allocated + \param filename The source file which allocated the memory + \param line The source line which allocated the memory + \return The allocated block of memory. + */ + void* allocate(size_t size, const char* typeName, const char* filename, int line) + { + void* mem = mAllocator.allocate(size, typeName, filename, line); + + if(!mem) + { + mError.reportError(PxErrorCode::eABORT, "User allocator returned NULL.", __FILE__, __LINE__); + return NULL; + } + + if((reinterpret_cast(mem) & 15)) + { + mError.reportError(PxErrorCode::eABORT, "Allocations must be 16-byte aligned.", __FILE__, __LINE__); + return NULL; + } + + for(uint32_t i = 0; i < mListeners.size(); i++) + mListeners[i]->onAllocation(size, typeName, filename, line, mem); + + return mem; + } + + /** + \brief Frees memory previously allocated by allocate(). + + Threading: This function should be thread safe as it can be called in the context of the user thread + and physics processing thread(s). + + \param ptr Memory to free. + */ + void deallocate(void* ptr) + { + for(uint32_t i = 0; i < mListeners.size(); i++) + { + mListeners[i]->onDeallocation(ptr); + } + mAllocator.deallocate(ptr); + } + + private: + PxAllocatorCallback& mAllocator; + PxErrorCallback& mError; +}; + +/** +\brief Abstract base class for an application defined error callback that allows an external listener +to report errors. +*/ +class BroadcastingErrorCallback : public Broadcast +{ + PX_NOCOPY(BroadcastingErrorCallback) + public: + /** + \brief The default constructor. + */ + BroadcastingErrorCallback(PxErrorCallback& errorCallback) + { + registerListener(errorCallback); + } + + /** + \brief The default destructor. + */ + virtual ~BroadcastingErrorCallback() + { + mListeners.clear(); + } + + /** + \brief Reports an error code. + \param code Error code, see #PxErrorCode + \param message Message to display. + \param file File error occured in. + \param line Line number error occured on. + */ + void reportError(PxErrorCode::Enum code, const char* message, const char* file, int line) + { + for(uint32_t i = 0; i < mListeners.size(); i++) + mListeners[i]->reportError(code, message, file, line); + } +}; +} +} // namespace physx + +#endif // PSFOUNDATION_PXBROADCAST_H diff --git a/sources/PhysX/PhysX/source/foundation/include/PsCpu.h b/sources/PhysX/PhysX/source/foundation/include/PsCpu.h new file mode 100644 index 00000000..f9f77909 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsCpu.h @@ -0,0 +1,47 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSCPU_H +#define PSFOUNDATION_PSCPU_H + +#include "Ps.h" + +namespace physx +{ +namespace shdfnd +{ +class Cpu +{ + public: + static uint8_t getCpuId(); +}; +} +} + +#endif // #ifndef PSFOUNDATION_PSCPU_H diff --git a/sources/PhysX/PhysX/source/foundation/include/PsFPU.h b/sources/PhysX/PhysX/source/foundation/include/PsFPU.h new file mode 100644 index 00000000..ac9ab3dd --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsFPU.h @@ -0,0 +1,93 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSFPU_H +#define PSFOUNDATION_PSFPU_H + +#include "Ps.h" +#include "PsIntrinsics.h" + +#define PX_IR(x) ((uint32_t&)(x)) // integer representation of a floating-point value. +#define PX_SIR(x) ((int32_t&)(x)) // signed integer representation of a floating-point value. +#define PX_FR(x) ((float&)(x)) // floating-point representation of a integer value. + +#define PX_FPU_GUARD shdfnd::FPUGuard scopedFpGuard; +#define PX_SIMD_GUARD shdfnd::SIMDGuard scopedFpGuard; + +namespace physx +{ +namespace shdfnd +{ +// sets the default SDK state for scalar and SIMD units +class PX_FOUNDATION_API FPUGuard +{ + public: + FPUGuard(); // set fpu control word for PhysX + ~FPUGuard(); // restore fpu control word + private: + uint32_t mControlWords[8]; +}; + +// sets default SDK state for simd unit only, lighter weight than FPUGuard +class SIMDGuard +{ + public: + PX_INLINE SIMDGuard(); // set simd control word for PhysX + PX_INLINE ~SIMDGuard(); // restore simd control word + private: + uint32_t mControlWord; +}; + +/** +\brief Enables floating point exceptions for the scalar and SIMD unit +*/ +PX_FOUNDATION_API void enableFPExceptions(); + +/** +\brief Disables floating point exceptions for the scalar and SIMD unit +*/ +PX_FOUNDATION_API void disableFPExceptions(); + +} // namespace shdfnd +} // namespace physx + +#if PX_WINDOWS_FAMILY || PX_XBOXONE +#include "windows/PsWindowsFPU.h" +#elif (PX_LINUX && PX_SSE2) || PX_PS4 || PX_OSX +#include "unix/PsUnixFPU.h" +#else +PX_INLINE physx::shdfnd::SIMDGuard::SIMDGuard() +{ +} +PX_INLINE physx::shdfnd::SIMDGuard::~SIMDGuard() +{ +} +#endif + +#endif // #ifndef PSFOUNDATION_PSFPU_H diff --git a/sources/PhysX/PhysX/source/foundation/include/PsFoundation.h b/sources/PhysX/PhysX/source/foundation/include/PsFoundation.h new file mode 100644 index 00000000..5315556d --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsFoundation.h @@ -0,0 +1,223 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_FOUNDATION_PSFOUNDATION_H +#define PX_FOUNDATION_PSFOUNDATION_H + +#include "foundation/PxErrors.h" +#include "foundation/PxProfiler.h" + +#include "PxFoundation.h" + +#include "PsBroadcast.h" +#include "PsAllocator.h" +#include "PsTempAllocator.h" +#include "PsMutex.h" +#include "PsHashMap.h" +#include "PsUserAllocated.h" + +#include + +namespace physx +{ +namespace shdfnd +{ + +#if PX_VC +#pragma warning(push) +#pragma warning(disable : 4251) // class needs to have dll-interface to be used by clients of class +#endif + +class PX_FOUNDATION_API Foundation : public PxFoundation, public UserAllocated +{ + PX_NOCOPY(Foundation) + + public: + typedef MutexT Mutex; + + typedef HashMap, NonTrackingAllocator> AllocNameMap; + typedef Array AllocFreeTable; + + public: + // factory + // note, you MUST eventually call release if createInstance returned true! + static Foundation* createInstance(PxU32 version, PxErrorCallback& errc, PxAllocatorCallback& alloc); + static Foundation& getInstance(); + static void setInstance(Foundation& foundation); + void release(); + static void incRefCount(); // this call requires a foundation object to exist already + static void decRefCount(); // this call requires a foundation object to exist already + + // Begin Errors + virtual PxErrorCallback& getErrorCallback() + { + return mErrorCallback; + } // Return the user's error callback + PxErrorCallback& getInternalErrorCallback() + { + return mBroadcastingError; + } // Return the broadcasting error callback + + void registerErrorCallback(PxErrorCallback& listener); + void deregisterErrorCallback(PxErrorCallback& listener); + + virtual void setErrorLevel(PxErrorCode::Enum mask) + { + mErrorMask = mask; + } + virtual PxErrorCode::Enum getErrorLevel() const + { + return mErrorMask; + } + + void error(PxErrorCode::Enum, const char* file, int line, const char* messageFmt, ...); // Report errors with the + // broadcasting + void errorImpl(PxErrorCode::Enum, const char* file, int line, const char* messageFmt, va_list); // error callback + static PxU32 getWarnOnceTimestamp(); + + // End errors + + // Begin Allocations + virtual PxAllocatorCallback& getAllocatorCallback() + { + return mAllocatorCallback; + } // Return the user's allocator callback + PxAllocatorCallback& getAllocator() + { + return mBroadcastingAllocator; + } // Return the broadcasting allocator + + void registerAllocationListener(physx::shdfnd::AllocationListener& listener); + void deregisterAllocationListener(physx::shdfnd::AllocationListener& listener); + + virtual bool getReportAllocationNames() const + { + return mReportAllocationNames; + } + virtual void setReportAllocationNames(bool value) + { + mReportAllocationNames = value; + } + + PX_INLINE AllocNameMap& getNamedAllocMap() + { + return mNamedAllocMap; + } + PX_INLINE Mutex& getNamedAllocMutex() + { + return mNamedAllocMutex; + } + + PX_INLINE AllocFreeTable& getTempAllocFreeTable() + { + return mTempAllocFreeTable; + } + PX_INLINE Mutex& getTempAllocMutex() + { + return mTempAllocMutex; + } + // End allocations + + private: + static void destroyInstance(); + + Foundation(PxErrorCallback& errc, PxAllocatorCallback& alloc); + ~Foundation(); + + // init order is tricky here: the mutexes require the allocator, the allocator may require the error stream + PxAllocatorCallback& mAllocatorCallback; + PxErrorCallback& mErrorCallback; + + BroadcastingAllocator mBroadcastingAllocator; + BroadcastingErrorCallback mBroadcastingError; + + bool mReportAllocationNames; + + PxErrorCode::Enum mErrorMask; + Mutex mErrorMutex; + + AllocNameMap mNamedAllocMap; + Mutex mNamedAllocMutex; + + AllocFreeTable mTempAllocFreeTable; + Mutex mTempAllocMutex; + + Mutex mListenerMutex; + + static Foundation* mInstance; + static PxU32 mRefCount; + static PxU32 mWarnOnceTimestap; +}; +#if PX_VC +#pragma warning(pop) +#endif + +PX_INLINE Foundation& getFoundation() +{ + return Foundation::getInstance(); +} + +PX_INLINE void setFoundationInstance(Foundation& foundation) +{ + Foundation::setInstance(foundation); +} + +} // namespace shdfnd +} // namespace physx + +// shortcut macros: +// usage: Foundation::error(PX_WARN, "static friction %f is is lower than dynamic friction %d", sfr, dfr); +#define PX_WARN ::physx::PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__ +#define PX_INFO ::physx::PxErrorCode::eDEBUG_INFO, __FILE__, __LINE__ + +#if PX_DEBUG || PX_CHECKED +#define PX_WARN_ONCE(string) \ + { \ + static PxU32 timestamp = 0; \ + if(timestamp != Ps::getFoundation().getWarnOnceTimestamp()) \ + { \ + timestamp = Ps::getFoundation().getWarnOnceTimestamp(); \ + Ps::getFoundation().error(PX_WARN, string); \ + } \ + \ +} +#define PX_WARN_ONCE_IF(condition, string) \ + { \ + if(condition) \ + { \ + PX_WARN_ONCE(string) \ + } \ + \ +} +#else +#define PX_WARN_ONCE(string) ((void)0) +#define PX_WARN_ONCE_IF(condition, string) ((void)0) +#endif + +#endif diff --git a/sources/PhysX/PhysX/source/foundation/include/PsHash.h b/sources/PhysX/PhysX/source/foundation/include/PsHash.h new file mode 100644 index 00000000..68faddcd --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsHash.h @@ -0,0 +1,168 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSHASH_H +#define PSFOUNDATION_PSHASH_H + +#include "Ps.h" +#include "PsBasicTemplates.h" + +#if PX_VC +#pragma warning(push) +#pragma warning(disable : 4302) +#endif + +#if PX_LINUX +#include "foundation/PxSimpleTypes.h" +#endif + +/*! +Central definition of hash functions +*/ + +namespace physx +{ +namespace shdfnd +{ +// Hash functions + +// Thomas Wang's 32 bit mix +// http://www.cris.com/~Ttwang/tech/inthash.htm +PX_FORCE_INLINE uint32_t hash(const uint32_t key) +{ + uint32_t k = key; + k += ~(k << 15); + k ^= (k >> 10); + k += (k << 3); + k ^= (k >> 6); + k += ~(k << 11); + k ^= (k >> 16); + return uint32_t(k); +} + +// // size_t in emscripten is an unsigned long +// PX_FORCE_INLINE uint32_t hash(const unsigned long key) +// { +// return hash(uint32_t(key)); +// } + +PX_FORCE_INLINE uint32_t hash(const int32_t key) +{ + return hash(uint32_t(key)); +} + +// Thomas Wang's 64 bit mix +// http://www.cris.com/~Ttwang/tech/inthash.htm +PX_FORCE_INLINE uint32_t hash(const uint64_t key) +{ + uint64_t k = key; + k += ~(k << 32); + k ^= (k >> 22); + k += ~(k << 13); + k ^= (k >> 8); + k += (k << 3); + k ^= (k >> 15); + k += ~(k << 27); + k ^= (k >> 31); + return uint32_t(UINT32_MAX & k); +} + +#if PX_APPLE_FAMILY +// hash for size_t, to make gcc happy +PX_INLINE uint32_t hash(const size_t key) +{ +#if PX_P64_FAMILY + return hash(uint64_t(key)); +#else + return hash(uint32_t(key)); +#endif +} +#endif + +// Hash function for pointers +PX_INLINE uint32_t hash(const void* ptr) +{ +#if PX_P64_FAMILY + return hash(uint64_t(ptr)); +#else + return hash(uint32_t(UINT32_MAX & size_t(ptr))); +#endif +} + +// Hash function for pairs +template +PX_INLINE uint32_t hash(const Pair& p) +{ + uint32_t seed = 0x876543; + uint32_t m = 1000007; + return hash(p.second) ^ (m * (hash(p.first) ^ (m * seed))); +} + +// hash object for hash map template parameter +template +struct Hash +{ + uint32_t operator()(const Key& k) const + { + return hash(k); + } + bool equal(const Key& k0, const Key& k1) const + { + return k0 == k1; + } +}; + +// specialization for strings +template <> +struct Hash +{ + public: + uint32_t operator()(const char* _string) const + { + // "DJB" string hash + const uint8_t* string = reinterpret_cast(_string); + uint32_t h = 5381; + for(const uint8_t* ptr = string; *ptr; ptr++) + h = ((h << 5) + h) ^ uint32_t(*ptr); + return h; + } + bool equal(const char* string0, const char* string1) const + { + return !strcmp(string0, string1); + } +}; + +} // namespace shdfnd +} // namespace physx + +#if PX_VC +#pragma warning(pop) +#endif + +#endif // #ifndef PSFOUNDATION_PSHASH_H diff --git a/sources/PhysX/PhysX/source/foundation/include/PsHashInternals.h b/sources/PhysX/PhysX/source/foundation/include/PsHashInternals.h new file mode 100644 index 00000000..8ff9d670 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsHashInternals.h @@ -0,0 +1,795 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSHASHINTERNALS_H +#define PSFOUNDATION_PSHASHINTERNALS_H + +#include "PsBasicTemplates.h" +#include "PsArray.h" +#include "PsBitUtils.h" +#include "PsHash.h" +#include "foundation/PxIntrinsics.h" + +#if PX_VC +#pragma warning(push) +#pragma warning(disable : 4127) // conditional expression is constant +#endif +namespace physx +{ +namespace shdfnd +{ +namespace internal +{ +template +class HashBase : private Allocator +{ + void init(uint32_t initialTableSize, float loadFactor) + { + mBuffer = NULL; + mEntries = NULL; + mEntriesNext = NULL; + mHash = NULL; + mEntriesCapacity = 0; + mHashSize = 0; + mLoadFactor = loadFactor; + mFreeList = uint32_t(EOL); + mTimestamp = 0; + mEntriesCount = 0; + + if(initialTableSize) + reserveInternal(initialTableSize); + } + + public: + typedef Entry EntryType; + + HashBase(uint32_t initialTableSize = 64, float loadFactor = 0.75f) : Allocator(PX_DEBUG_EXP("hashBase")) + { + init(initialTableSize, loadFactor); + } + + HashBase(uint32_t initialTableSize, float loadFactor, const Allocator& alloc) : Allocator(alloc) + { + init(initialTableSize, loadFactor); + } + + HashBase(const Allocator& alloc) : Allocator(alloc) + { + init(64, 0.75f); + } + + ~HashBase() + { + destroy(); // No need to clear() + + if(mBuffer) + Allocator::deallocate(mBuffer); + } + + static const uint32_t EOL = 0xffffffff; + + PX_INLINE Entry* create(const Key& k, bool& exists) + { + uint32_t h = 0; + if(mHashSize) + { + h = hash(k); + uint32_t index = mHash[h]; + while(index != EOL && !HashFn().equal(GetKey()(mEntries[index]), k)) + index = mEntriesNext[index]; + exists = index != EOL; + if(exists) + return mEntries + index; + } + else + exists = false; + + if(freeListEmpty()) + { + grow(); + h = hash(k); + } + + uint32_t entryIndex = freeListGetNext(); + + mEntriesNext[entryIndex] = mHash[h]; + mHash[h] = entryIndex; + + mEntriesCount++; + mTimestamp++; + + return mEntries + entryIndex; + } + + PX_INLINE const Entry* find(const Key& k) const + { + if(!mEntriesCount) + return NULL; + + const uint32_t h = hash(k); + uint32_t index = mHash[h]; + while(index != EOL && !HashFn().equal(GetKey()(mEntries[index]), k)) + index = mEntriesNext[index]; + return index != EOL ? mEntries + index : NULL; + } + + PX_INLINE bool erase(const Key& k, Entry& e) + { + if(!mEntriesCount) + return false; + + const uint32_t h = hash(k); + uint32_t* ptr = mHash + h; + while(*ptr != EOL && !HashFn().equal(GetKey()(mEntries[*ptr]), k)) + ptr = mEntriesNext + *ptr; + + if(*ptr == EOL) + return false; + + PX_PLACEMENT_NEW(&e, Entry)(mEntries[*ptr]); + + return eraseInternal(ptr); + } + + PX_INLINE bool erase(const Key& k) + { + if(!mEntriesCount) + return false; + + const uint32_t h = hash(k); + uint32_t* ptr = mHash + h; + while(*ptr != EOL && !HashFn().equal(GetKey()(mEntries[*ptr]), k)) + ptr = mEntriesNext + *ptr; + + if(*ptr == EOL) + return false; + + return eraseInternal(ptr); + } + + PX_INLINE uint32_t size() const + { + return mEntriesCount; + } + + PX_INLINE uint32_t capacity() const + { + return mHashSize; + } + + void clear() + { + if(!mHashSize || mEntriesCount == 0) + return; + + destroy(); + + intrinsics::memSet(mHash, EOL, mHashSize * sizeof(uint32_t)); + + const uint32_t sizeMinus1 = mEntriesCapacity - 1; + for(uint32_t i = 0; i < sizeMinus1; i++) + { + prefetchLine(mEntriesNext + i, 128); + mEntriesNext[i] = i + 1; + } + mEntriesNext[mEntriesCapacity - 1] = uint32_t(EOL); + mFreeList = 0; + mEntriesCount = 0; + } + + void reserve(uint32_t size) + { + if(size > mHashSize) + reserveInternal(size); + } + + PX_INLINE const Entry* getEntries() const + { + return mEntries; + } + + PX_INLINE Entry* insertUnique(const Key& k) + { + PX_ASSERT(find(k) == NULL); + uint32_t h = hash(k); + + uint32_t entryIndex = freeListGetNext(); + + mEntriesNext[entryIndex] = mHash[h]; + mHash[h] = entryIndex; + + mEntriesCount++; + mTimestamp++; + + return mEntries + entryIndex; + } + + private: + void destroy() + { + for(uint32_t i = 0; i < mHashSize; i++) + { + for(uint32_t j = mHash[i]; j != EOL; j = mEntriesNext[j]) + mEntries[j].~Entry(); + } + } + + template + PX_NOINLINE void copy(const HashBase& other); + + // free list management - if we're coalescing, then we use mFreeList to hold + // the top of the free list and it should always be equal to size(). Otherwise, + // we build a free list in the next() pointers. + + PX_INLINE void freeListAdd(uint32_t index) + { + if(compacting) + { + mFreeList--; + PX_ASSERT(mFreeList == mEntriesCount); + } + else + { + mEntriesNext[index] = mFreeList; + mFreeList = index; + } + } + + PX_INLINE void freeListAdd(uint32_t start, uint32_t end) + { + if(!compacting) + { + for(uint32_t i = start; i < end - 1; i++) // add the new entries to the free list + mEntriesNext[i] = i + 1; + + // link in old free list + mEntriesNext[end - 1] = mFreeList; + PX_ASSERT(mFreeList != end - 1); + mFreeList = start; + } + else if(mFreeList == EOL) // don't reset the free ptr for the compacting hash unless it's empty + mFreeList = start; + } + + PX_INLINE uint32_t freeListGetNext() + { + PX_ASSERT(!freeListEmpty()); + if(compacting) + { + PX_ASSERT(mFreeList == mEntriesCount); + return mFreeList++; + } + else + { + uint32_t entryIndex = mFreeList; + mFreeList = mEntriesNext[mFreeList]; + return entryIndex; + } + } + + PX_INLINE bool freeListEmpty() const + { + if(compacting) + return mEntriesCount == mEntriesCapacity; + else + return mFreeList == EOL; + } + + PX_INLINE void replaceWithLast(uint32_t index) + { + PX_PLACEMENT_NEW(mEntries + index, Entry)(mEntries[mEntriesCount]); + mEntries[mEntriesCount].~Entry(); + mEntriesNext[index] = mEntriesNext[mEntriesCount]; + + uint32_t h = hash(GetKey()(mEntries[index])); + uint32_t* ptr; + for(ptr = mHash + h; *ptr != mEntriesCount; ptr = mEntriesNext + *ptr) + PX_ASSERT(*ptr != EOL); + *ptr = index; + } + + PX_INLINE uint32_t hash(const Key& k, uint32_t hashSize) const + { + return HashFn()(k) & (hashSize - 1); + } + + PX_INLINE uint32_t hash(const Key& k) const + { + return hash(k, mHashSize); + } + + PX_INLINE bool eraseInternal(uint32_t* ptr) + { + const uint32_t index = *ptr; + + *ptr = mEntriesNext[index]; + + mEntries[index].~Entry(); + + mEntriesCount--; + mTimestamp++; + + if (compacting && index != mEntriesCount) + replaceWithLast(index); + + freeListAdd(index); + return true; + } + + void reserveInternal(uint32_t size) + { + if(!isPowerOfTwo(size)) + size = nextPowerOfTwo(size); + + PX_ASSERT(!(size & (size - 1))); + + // decide whether iteration can be done on the entries directly + bool resizeCompact = compacting || freeListEmpty(); + + // define new table sizes + uint32_t oldEntriesCapacity = mEntriesCapacity; + uint32_t newEntriesCapacity = uint32_t(float(size) * mLoadFactor); + uint32_t newHashSize = size; + + // allocate new common buffer and setup pointers to new tables + uint8_t* newBuffer; + uint32_t* newHash; + uint32_t* newEntriesNext; + Entry* newEntries; + { + uint32_t newHashByteOffset = 0; + uint32_t newEntriesNextBytesOffset = newHashByteOffset + newHashSize * sizeof(uint32_t); + uint32_t newEntriesByteOffset = newEntriesNextBytesOffset + newEntriesCapacity * sizeof(uint32_t); + newEntriesByteOffset += (16 - (newEntriesByteOffset & 15)) & 15; + uint32_t newBufferByteSize = newEntriesByteOffset + newEntriesCapacity * sizeof(Entry); + + newBuffer = reinterpret_cast(Allocator::allocate(newBufferByteSize, __FILE__, __LINE__)); + PX_ASSERT(newBuffer); + + newHash = reinterpret_cast(newBuffer + newHashByteOffset); + newEntriesNext = reinterpret_cast(newBuffer + newEntriesNextBytesOffset); + newEntries = reinterpret_cast(newBuffer + newEntriesByteOffset); + } + + // initialize new hash table + intrinsics::memSet(newHash, uint32_t(EOL), newHashSize * sizeof(uint32_t)); + + // iterate over old entries, re-hash and create new entries + if(resizeCompact) + { + // check that old free list is empty - we don't need to copy the next entries + PX_ASSERT(compacting || mFreeList == EOL); + + for(uint32_t index = 0; index < mEntriesCount; ++index) + { + uint32_t h = hash(GetKey()(mEntries[index]), newHashSize); + newEntriesNext[index] = newHash[h]; + newHash[h] = index; + + PX_PLACEMENT_NEW(newEntries + index, Entry)(mEntries[index]); + mEntries[index].~Entry(); + } + } + else + { + // copy old free list, only required for non compact resizing + intrinsics::memCopy(newEntriesNext, mEntriesNext, mEntriesCapacity * sizeof(uint32_t)); + + for(uint32_t bucket = 0; bucket < mHashSize; bucket++) + { + uint32_t index = mHash[bucket]; + while(index != EOL) + { + uint32_t h = hash(GetKey()(mEntries[index]), newHashSize); + newEntriesNext[index] = newHash[h]; + PX_ASSERT(index != newHash[h]); + + newHash[h] = index; + + PX_PLACEMENT_NEW(newEntries + index, Entry)(mEntries[index]); + mEntries[index].~Entry(); + + index = mEntriesNext[index]; + } + } + } + + // swap buffer and pointers + Allocator::deallocate(mBuffer); + mBuffer = newBuffer; + mHash = newHash; + mHashSize = newHashSize; + mEntriesNext = newEntriesNext; + mEntries = newEntries; + mEntriesCapacity = newEntriesCapacity; + + freeListAdd(oldEntriesCapacity, newEntriesCapacity); + } + + void grow() + { + PX_ASSERT((mFreeList == EOL) || (compacting && (mEntriesCount == mEntriesCapacity))); + + uint32_t size = mHashSize == 0 ? 16 : mHashSize * 2; + reserve(size); + } + + uint8_t* mBuffer; + Entry* mEntries; + uint32_t* mEntriesNext; // same size as mEntries + uint32_t* mHash; + uint32_t mEntriesCapacity; + uint32_t mHashSize; + float mLoadFactor; + uint32_t mFreeList; + uint32_t mTimestamp; + uint32_t mEntriesCount; // number of entries + + public: + class Iter + { + public: + PX_INLINE Iter(HashBase& b) : mBucket(0), mEntry(uint32_t(b.EOL)), mTimestamp(b.mTimestamp), mBase(b) + { + if(mBase.mEntriesCapacity > 0) + { + mEntry = mBase.mHash[0]; + skip(); + } + } + + PX_INLINE void check() const + { + PX_ASSERT(mTimestamp == mBase.mTimestamp); + } + PX_INLINE const Entry& operator*() const + { + check(); + return mBase.mEntries[mEntry]; + } + PX_INLINE Entry& operator*() + { + check(); + return mBase.mEntries[mEntry]; + } + PX_INLINE const Entry* operator->() const + { + check(); + return mBase.mEntries + mEntry; + } + PX_INLINE Entry* operator->() + { + check(); + return mBase.mEntries + mEntry; + } + PX_INLINE Iter operator++() + { + check(); + advance(); + return *this; + } + PX_INLINE Iter operator++(int) + { + check(); + Iter i = *this; + advance(); + return i; + } + PX_INLINE bool done() const + { + check(); + return mEntry == mBase.EOL; + } + + private: + PX_INLINE void advance() + { + mEntry = mBase.mEntriesNext[mEntry]; + skip(); + } + PX_INLINE void skip() + { + while(mEntry == mBase.EOL) + { + if(++mBucket == mBase.mHashSize) + break; + mEntry = mBase.mHash[mBucket]; + } + } + + Iter& operator=(const Iter&); + + uint32_t mBucket; + uint32_t mEntry; + uint32_t mTimestamp; + HashBase& mBase; + }; + + /*! + Iterate over entries in a hash base and allow entry erase while iterating + */ + class EraseIterator + { + public: + PX_INLINE EraseIterator(HashBase& b): mBase(b) + { + reset(); + } + + PX_INLINE Entry* eraseCurrentGetNext(bool eraseCurrent) + { + if(eraseCurrent && mCurrentEntryIndexPtr) + { + mBase.eraseInternal(mCurrentEntryIndexPtr); + // if next was valid return the same ptr, if next was EOL search new hash entry + if(*mCurrentEntryIndexPtr != mBase.EOL) + return mBase.mEntries + *mCurrentEntryIndexPtr; + else + return traverseHashEntries(); + } + + // traverse mHash to find next entry + if(mCurrentEntryIndexPtr == NULL) + return traverseHashEntries(); + + const uint32_t index = *mCurrentEntryIndexPtr; + if(mBase.mEntriesNext[index] == mBase.EOL) + { + return traverseHashEntries(); + } + else + { + mCurrentEntryIndexPtr = mBase.mEntriesNext + index; + return mBase.mEntries + *mCurrentEntryIndexPtr; + } + } + + PX_INLINE void reset() + { + mCurrentHashIndex = 0; + mCurrentEntryIndexPtr = NULL; + } + + private: + PX_INLINE Entry* traverseHashEntries() + { + mCurrentEntryIndexPtr = NULL; + while (mCurrentEntryIndexPtr == NULL && mCurrentHashIndex < mBase.mHashSize) + { + if (mBase.mHash[mCurrentHashIndex] != mBase.EOL) + { + mCurrentEntryIndexPtr = mBase.mHash + mCurrentHashIndex; + mCurrentHashIndex++; + return mBase.mEntries + *mCurrentEntryIndexPtr; + } + else + { + mCurrentHashIndex++; + } + } + return NULL; + } + + EraseIterator& operator=(const EraseIterator&); + private: + uint32_t* mCurrentEntryIndexPtr; + uint32_t mCurrentHashIndex; + HashBase& mBase; + }; +}; + +template +template +PX_NOINLINE void +HashBase::copy(const HashBase& other) +{ + reserve(other.mEntriesCount); + + for(uint32_t i = 0; i < other.mEntriesCount; i++) + { + for(uint32_t j = other.mHash[i]; j != EOL; j = other.mEntriesNext[j]) + { + const Entry& otherEntry = other.mEntries[j]; + + bool exists; + Entry* newEntry = create(GK()(otherEntry), exists); + PX_ASSERT(!exists); + + PX_PLACEMENT_NEW(newEntry, Entry)(otherEntry); + } + } +} + +template ::Type, bool Coalesced = false> +class HashSetBase +{ + PX_NOCOPY(HashSetBase) + public: + struct GetKey + { + PX_INLINE const Key& operator()(const Key& e) + { + return e; + } + }; + + typedef HashBase BaseMap; + typedef typename BaseMap::Iter Iterator; + + HashSetBase(uint32_t initialTableSize, float loadFactor, const Allocator& alloc) + : mBase(initialTableSize, loadFactor, alloc) + { + } + + HashSetBase(const Allocator& alloc) : mBase(64, 0.75f, alloc) + { + } + + HashSetBase(uint32_t initialTableSize = 64, float loadFactor = 0.75f) : mBase(initialTableSize, loadFactor) + { + } + + bool insert(const Key& k) + { + bool exists; + Key* e = mBase.create(k, exists); + if(!exists) + PX_PLACEMENT_NEW(e, Key)(k); + return !exists; + } + + PX_INLINE bool contains(const Key& k) const + { + return mBase.find(k) != 0; + } + PX_INLINE bool erase(const Key& k) + { + return mBase.erase(k); + } + PX_INLINE uint32_t size() const + { + return mBase.size(); + } + PX_INLINE uint32_t capacity() const + { + return mBase.capacity(); + } + PX_INLINE void reserve(uint32_t size) + { + mBase.reserve(size); + } + PX_INLINE void clear() + { + mBase.clear(); + } + + protected: + BaseMap mBase; +}; + +template >::Type> +class HashMapBase +{ + PX_NOCOPY(HashMapBase) + public: + typedef Pair Entry; + + struct GetKey + { + PX_INLINE const Key& operator()(const Entry& e) + { + return e.first; + } + }; + + typedef HashBase BaseMap; + typedef typename BaseMap::Iter Iterator; + typedef typename BaseMap::EraseIterator EraseIterator; + + HashMapBase(uint32_t initialTableSize, float loadFactor, const Allocator& alloc) + : mBase(initialTableSize, loadFactor, alloc) + { + } + + HashMapBase(const Allocator& alloc) : mBase(64, 0.75f, alloc) + { + } + + HashMapBase(uint32_t initialTableSize = 64, float loadFactor = 0.75f) : mBase(initialTableSize, loadFactor) + { + } + + bool insert(const Key /*&*/ k, const Value /*&*/ v) + { + bool exists; + Entry* e = mBase.create(k, exists); + if(!exists) + PX_PLACEMENT_NEW(e, Entry)(k, v); + return !exists; + } + + Value& operator[](const Key& k) + { + bool exists; + Entry* e = mBase.create(k, exists); + if(!exists) + PX_PLACEMENT_NEW(e, Entry)(k, Value()); + + return e->second; + } + + PX_INLINE const Entry* find(const Key& k) const + { + return mBase.find(k); + } + PX_INLINE bool erase(const Key& k) + { + return mBase.erase(k); + } + PX_INLINE bool erase(const Key& k, Entry& e) + { + return mBase.erase(k, e); + } + PX_INLINE uint32_t size() const + { + return mBase.size(); + } + PX_INLINE uint32_t capacity() const + { + return mBase.capacity(); + } + PX_INLINE Iterator getIterator() + { + return Iterator(mBase); + } + PX_INLINE EraseIterator getEraseIterator() + { + return EraseIterator(mBase); + } + PX_INLINE void reserve(uint32_t size) + { + mBase.reserve(size); + } + PX_INLINE void clear() + { + mBase.clear(); + } + + protected: + BaseMap mBase; +}; +} + +} // namespace shdfnd +} // namespace physx + +#if PX_VC +#pragma warning(pop) +#endif +#endif // #ifndef PSFOUNDATION_PSHASHINTERNALS_H diff --git a/sources/PhysX/PhysX/source/foundation/include/PsHashMap.h b/sources/PhysX/PhysX/source/foundation/include/PsHashMap.h new file mode 100644 index 00000000..dac0ffc7 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsHashMap.h @@ -0,0 +1,118 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSHASHMAP_H +#define PSFOUNDATION_PSHASHMAP_H + +#include "PsHashInternals.h" + +// TODO: make this doxy-format +// +// This header defines two hash maps. Hash maps +// * support custom initial table sizes (rounded up internally to power-of-2) +// * support custom static allocator objects +// * auto-resize, based on a load factor (i.e. a 64-entry .75 load factor hash will resize +// when the 49th element is inserted) +// * are based on open hashing +// * have O(1) contains, erase +// +// Maps have STL-like copying semantics, and properly initialize and destruct copies of objects +// +// There are two forms of map: coalesced and uncoalesced. Coalesced maps keep the entries in the +// initial segment of an array, so are fast to iterate over; however deletion is approximately +// twice as expensive. +// +// HashMap: +// bool insert(const Key& k, const Value& v) O(1) amortized (exponential resize policy) +// Value & operator[](const Key& k) O(1) for existing objects, else O(1) amortized +// const Entry * find(const Key& k); O(1) +// bool erase(const T& k); O(1) +// uint32_t size(); constant +// void reserve(uint32_t size); O(MAX(currentOccupancy,size)) +// void clear(); O(currentOccupancy) (with zero constant for objects +// without +// destructors) +// Iterator getIterator(); +// +// operator[] creates an entry if one does not exist, initializing with the default constructor. +// CoalescedHashMap does not support getIterator, but instead supports +// const Key *getEntries(); +// +// Use of iterators: +// +// for(HashMap::Iterator iter = test.getIterator(); !iter.done(); ++iter) +// myFunction(iter->first, iter->second); + +namespace physx +{ +namespace shdfnd +{ +template , class Allocator = NonTrackingAllocator> +class HashMap : public internal::HashMapBase +{ + public: + typedef internal::HashMapBase HashMapBase; + typedef typename HashMapBase::Iterator Iterator; + + HashMap(uint32_t initialTableSize = 64, float loadFactor = 0.75f) : HashMapBase(initialTableSize, loadFactor) + { + } + HashMap(uint32_t initialTableSize, float loadFactor, const Allocator& alloc) + : HashMapBase(initialTableSize, loadFactor, alloc) + { + } + HashMap(const Allocator& alloc) : HashMapBase(64, 0.75f, alloc) + { + } + Iterator getIterator() + { + return Iterator(HashMapBase::mBase); + } +}; + +template , class Allocator = NonTrackingAllocator> +class CoalescedHashMap : public internal::HashMapBase +{ + public: + typedef internal::HashMapBase HashMapBase; + + CoalescedHashMap(uint32_t initialTableSize = 64, float loadFactor = 0.75f) + : HashMapBase(initialTableSize, loadFactor) + { + } + const Pair* getEntries() const + { + return HashMapBase::mBase.getEntries(); + } +}; + +} // namespace shdfnd +} // namespace physx + +#endif // #ifndef PSFOUNDATION_PSHASHMAP_H diff --git a/sources/PhysX/PhysX/source/foundation/include/PsHashSet.h b/sources/PhysX/PhysX/source/foundation/include/PsHashSet.h new file mode 100644 index 00000000..7d63bca7 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsHashSet.h @@ -0,0 +1,127 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSHASHSET_H +#define PSFOUNDATION_PSHASHSET_H + +#include "PsHashInternals.h" + +// TODO: make this doxy-format + +// This header defines two hash sets. Hash sets +// * support custom initial table sizes (rounded up internally to power-of-2) +// * support custom static allocator objects +// * auto-resize, based on a load factor (i.e. a 64-entry .75 load factor hash will resize +// when the 49th element is inserted) +// * are based on open hashing +// +// Sets have STL-like copying semantics, and properly initialize and destruct copies of objects +// +// There are two forms of set: coalesced and uncoalesced. Coalesced sets keep the entries in the +// initial segment of an array, so are fast to iterate over; however deletion is approximately +// twice as expensive. +// +// HashSet: +// bool insert(const T& k) amortized O(1) (exponential resize policy) +// bool contains(const T& k) const; O(1) +// bool erase(const T& k); O(1) +// uint32_t size() const; constant +// void reserve(uint32_t size); O(MAX(size, currentOccupancy)) +// void clear(); O(currentOccupancy) (with zero constant for objects without +// destructors) +// Iterator getIterator(); +// +// Use of iterators: +// +// for(HashSet::Iterator iter = test.getIterator(); !iter.done(); ++iter) +// myFunction(*iter); +// +// CoalescedHashSet does not support getIterator, but instead supports +// const Key *getEntries(); +// +// insertion into a set already containing the element fails returning false, as does +// erasure of an element not in the set +// + +namespace physx +{ +namespace shdfnd +{ +template , class Allocator = NonTrackingAllocator> +class HashSet : public internal::HashSetBase +{ + public: + typedef internal::HashSetBase HashSetBase; + typedef typename HashSetBase::Iterator Iterator; + + HashSet(uint32_t initialTableSize = 64, float loadFactor = 0.75f) : HashSetBase(initialTableSize, loadFactor) + { + } + HashSet(uint32_t initialTableSize, float loadFactor, const Allocator& alloc) + : HashSetBase(initialTableSize, loadFactor, alloc) + { + } + HashSet(const Allocator& alloc) : HashSetBase(64, 0.75f, alloc) + { + } + Iterator getIterator() + { + return Iterator(HashSetBase::mBase); + } +}; + +template , class Allocator = NonTrackingAllocator> +class CoalescedHashSet : public internal::HashSetBase +{ + public: + typedef typename internal::HashSetBase HashSetBase; + + CoalescedHashSet(uint32_t initialTableSize = 64, float loadFactor = 0.75f) + : HashSetBase(initialTableSize, loadFactor) + { + } + + CoalescedHashSet(uint32_t initialTableSize, float loadFactor, const Allocator& alloc) + : HashSetBase(initialTableSize, loadFactor, alloc) + { + } + CoalescedHashSet(const Allocator& alloc) : HashSetBase(64, 0.75f, alloc) + { + } + + const Key* getEntries() const + { + return HashSetBase::mBase.getEntries(); + } +}; + +} // namespace shdfnd +} // namespace physx + +#endif // #ifndef PSFOUNDATION_PSHASHSET_H diff --git a/sources/PhysX/PhysX/source/foundation/include/PsInlineAllocator.h b/sources/PhysX/PhysX/source/foundation/include/PsInlineAllocator.h new file mode 100644 index 00000000..10b99d25 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsInlineAllocator.h @@ -0,0 +1,91 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSINLINEALLOCATOR_H +#define PSFOUNDATION_PSINLINEALLOCATOR_H + +#include "PsUserAllocated.h" + +namespace physx +{ +namespace shdfnd +{ +// this is used by the array class to allocate some space for a small number +// of objects along with the metadata +template +class InlineAllocator : private BaseAllocator +{ + public: + InlineAllocator(const PxEMPTY v) : BaseAllocator(v) + { + } + + InlineAllocator(const BaseAllocator& alloc = BaseAllocator()) : BaseAllocator(alloc), mBufferUsed(false) + { + } + + InlineAllocator(const InlineAllocator& aloc) : BaseAllocator(aloc), mBufferUsed(false) + { + } + + void* allocate(uint32_t size, const char* filename, int line) + { + if(!mBufferUsed && size <= N) + { + mBufferUsed = true; + return mBuffer; + } + return BaseAllocator::allocate(size, filename, line); + } + + void deallocate(void* ptr) + { + if(ptr == mBuffer) + mBufferUsed = false; + else + BaseAllocator::deallocate(ptr); + } + + PX_FORCE_INLINE uint8_t* getInlineBuffer() + { + return mBuffer; + } + PX_FORCE_INLINE bool isBufferUsed() const + { + return mBufferUsed; + } + + protected: + uint8_t mBuffer[N]; + bool mBufferUsed; +}; +} // namespace shdfnd +} // namespace physx + +#endif // #ifndef PSFOUNDATION_PSINLINEALLOCATOR_H diff --git a/sources/PhysX/PhysX/source/foundation/include/PsInlineAoS.h b/sources/PhysX/PhysX/source/foundation/include/PsInlineAoS.h new file mode 100644 index 00000000..bb90084d --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsInlineAoS.h @@ -0,0 +1,48 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSINLINEAOS_H +#define PSFOUNDATION_PSINLINEAOS_H + +#include "foundation/PxPreprocessor.h" + +#if PX_WINDOWS +#include "windows/PsWindowsTrigConstants.h" +#include "windows/PsWindowsInlineAoS.h" +#elif(PX_UNIX_FAMILY || PX_PS4 || PX_SWITCH || (PX_UWP && PX_NEON)) +#include "unix/PsUnixTrigConstants.h" +#include "unix/PsUnixInlineAoS.h" +#elif PX_XBOXONE +#include "XboxOne/PsXboxOneTrigConstants.h" +#include "XboxOne/PsXboxOneInlineAoS.h" +#else +#error "Platform not supported!" +#endif + +#endif diff --git a/sources/PhysX/PhysX/source/foundation/include/PsInlineArray.h b/sources/PhysX/PhysX/source/foundation/include/PsInlineArray.h new file mode 100644 index 00000000..542d1686 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsInlineArray.h @@ -0,0 +1,68 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSINLINEARRAY_H +#define PSFOUNDATION_PSINLINEARRAY_H + +#include "PsArray.h" +#include "PsInlineAllocator.h" + +namespace physx +{ +namespace shdfnd +{ + +// array that pre-allocates for N elements +template ::Type> +class InlineArray : public Array > +{ + typedef InlineAllocator Allocator; + + public: + InlineArray(const PxEMPTY v) : Array(v) + { + if(isInlined()) + this->mData = reinterpret_cast(Array::getInlineBuffer()); + } + + PX_INLINE bool isInlined() const + { + return Allocator::isBufferUsed(); + } + + PX_INLINE explicit InlineArray(const Alloc& alloc = Alloc()) : Array(alloc) + { + this->mData = this->allocate(N); + this->mCapacity = N; + } +}; +} // namespace shdfnd +} // namespace physx + +#endif // #ifndef PSFOUNDATION_PSINLINEARRAY_H diff --git a/sources/PhysX/PhysX/source/foundation/include/PsIntrinsics.h b/sources/PhysX/PhysX/source/foundation/include/PsIntrinsics.h new file mode 100644 index 00000000..d6a5afb1 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsIntrinsics.h @@ -0,0 +1,47 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSINTRINSICS_H +#define PSFOUNDATION_PSINTRINSICS_H + +#include "foundation/PxPreprocessor.h" + +#if PX_WINDOWS_FAMILY +#include "windows/PsWindowsIntrinsics.h" +#elif(PX_LINUX || PX_ANDROID || PX_APPLE_FAMILY || PX_PS4) +#include "unix/PsUnixIntrinsics.h" +#elif PX_XBOXONE +#include "XboxOne/PsXboxOneIntrinsics.h" +#elif PX_SWITCH +#include "switch/PsSwitchIntrinsics.h" +#else +#error "Platform not supported!" +#endif + +#endif // #ifndef PSFOUNDATION_PSINTRINSICS_H diff --git a/sources/PhysX/PhysX/source/foundation/include/PsMathUtils.h b/sources/PhysX/PhysX/source/foundation/include/PsMathUtils.h new file mode 100644 index 00000000..527ecc51 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsMathUtils.h @@ -0,0 +1,706 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSMATHUTILS_H +#define PSFOUNDATION_PSMATHUTILS_H + +#include "foundation/PxPreprocessor.h" +#include "foundation/PxTransform.h" +#include "foundation/PxMat33.h" +#include "Ps.h" +#include "PsIntrinsics.h" + +// General guideline is: if it's an abstract math function, it belongs here. +// If it's a math function where the inputs have specific semantics (e.g. +// separateSwingTwist) it doesn't. + +namespace physx +{ +namespace shdfnd +{ +/** +\brief sign returns the sign of its argument. The sign of zero is undefined. +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE PxF32 sign(const PxF32 a) +{ + return intrinsics::sign(a); +} + +/** +\brief sign returns the sign of its argument. The sign of zero is undefined. +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE PxF64 sign(const PxF64 a) +{ + return (a >= 0.0) ? 1.0 : -1.0; +} + +/** +\brief sign returns the sign of its argument. The sign of zero is undefined. +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE PxI32 sign(const PxI32 a) +{ + return (a >= 0) ? 1 : -1; +} + +/** +\brief Returns true if the two numbers are within eps of each other. +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE bool equals(const PxF32 a, const PxF32 b, const PxF32 eps) +{ + return (PxAbs(a - b) < eps); +} + +/** +\brief Returns true if the two numbers are within eps of each other. +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE bool equals(const PxF64 a, const PxF64 b, const PxF64 eps) +{ + return (PxAbs(a - b) < eps); +} + +/** +\brief The floor function returns a floating-point value representing the largest integer that is less than or equal to +x. +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE PxF32 floor(const PxF32 a) +{ + return floatFloor(a); +} + +/** +\brief The floor function returns a floating-point value representing the largest integer that is less than or equal to +x. +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE PxF64 floor(const PxF64 a) +{ + return ::floor(a); +} + +/** +\brief The ceil function returns a single value representing the smallest integer that is greater than or equal to x. +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE PxF32 ceil(const PxF32 a) +{ + return ::ceilf(a); +} + +/** +\brief The ceil function returns a double value representing the smallest integer that is greater than or equal to x. +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE PxF64 ceil(const PxF64 a) +{ + return ::ceil(a); +} + +/** +\brief mod returns the floating-point remainder of x / y. + +If the value of y is 0.0, mod returns a quiet NaN. +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE PxF32 mod(const PxF32 x, const PxF32 y) +{ + return PxF32(::fmodf(x, y)); +} + +/** +\brief mod returns the floating-point remainder of x / y. + +If the value of y is 0.0, mod returns a quiet NaN. +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE PxF64 mod(const PxF64 x, const PxF64 y) +{ + return ::fmod(x, y); +} + +/** +\brief Square. +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE PxF32 sqr(const PxF32 a) +{ + return a * a; +} + +/** +\brief Square. +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE PxF64 sqr(const PxF64 a) +{ + return a * a; +} + +/** +\brief Calculates x raised to the power of y. +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE PxF32 pow(const PxF32 x, const PxF32 y) +{ + return ::powf(x, y); +} + +/** +\brief Calculates x raised to the power of y. +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE PxF64 pow(const PxF64 x, const PxF64 y) +{ + return ::pow(x, y); +} + +/** +\brief Calculates e^n +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE PxF32 exp(const PxF32 a) +{ + return ::expf(a); +} +/** + +\brief Calculates e^n +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE PxF64 exp(const PxF64 a) +{ + return ::exp(a); +} + +/** +\brief Calculates 2^n +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE PxF32 exp2(const PxF32 a) +{ + return ::expf(a * 0.693147180559945309417f); +} +/** + +\brief Calculates 2^n +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE PxF64 exp2(const PxF64 a) +{ + return ::exp(a * 0.693147180559945309417); +} + +/** +\brief Calculates logarithms. +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE PxF32 logE(const PxF32 a) +{ + return ::logf(a); +} + +/** +\brief Calculates logarithms. +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE PxF64 logE(const PxF64 a) +{ + return ::log(a); +} + +/** +\brief Calculates logarithms. +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE PxF32 log2(const PxF32 a) +{ + return ::logf(a) / 0.693147180559945309417f; +} + +/** +\brief Calculates logarithms. +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE PxF64 log2(const PxF64 a) +{ + return ::log(a) / 0.693147180559945309417; +} + +/** +\brief Calculates logarithms. +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE PxF32 log10(const PxF32 a) +{ + return ::log10f(a); +} + +/** +\brief Calculates logarithms. +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE PxF64 log10(const PxF64 a) +{ + return ::log10(a); +} + +/** +\brief Converts degrees to radians. +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE PxF32 degToRad(const PxF32 a) +{ + return 0.01745329251994329547f * a; +} + +/** +\brief Converts degrees to radians. +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE PxF64 degToRad(const PxF64 a) +{ + return 0.01745329251994329547 * a; +} + +/** +\brief Converts radians to degrees. +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE PxF32 radToDeg(const PxF32 a) +{ + return 57.29577951308232286465f * a; +} + +/** +\brief Converts radians to degrees. +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE PxF64 radToDeg(const PxF64 a) +{ + return 57.29577951308232286465 * a; +} + +//! \brief compute sine and cosine at the same time. There is a 'fsincos' on PC that we probably want to use here +PX_CUDA_CALLABLE PX_FORCE_INLINE void sincos(const PxF32 radians, PxF32& sin, PxF32& cos) +{ + /* something like: + _asm fld Local + _asm fsincos + _asm fstp LocalCos + _asm fstp LocalSin + */ + sin = PxSin(radians); + cos = PxCos(radians); +} + +/** +\brief uniform random number in [a,b] +*/ +PX_FORCE_INLINE PxI32 rand(const PxI32 a, const PxI32 b) +{ + return a + PxI32(::rand() % (b - a + 1)); +} + +/** +\brief uniform random number in [a,b] +*/ +PX_FORCE_INLINE PxF32 rand(const PxF32 a, const PxF32 b) +{ + return a + (b - a) * ::rand() / RAND_MAX; +} + +//! \brief return angle between two vectors in radians +PX_CUDA_CALLABLE PX_FORCE_INLINE PxF32 angle(const PxVec3& v0, const PxVec3& v1) +{ + const PxF32 cos = v0.dot(v1); // |v0|*|v1|*Cos(Angle) + const PxF32 sin = (v0.cross(v1)).magnitude(); // |v0|*|v1|*Sin(Angle) + return PxAtan2(sin, cos); +} + +//! If possible use instead fsel on the dot product /*fsel(d.dot(p),onething,anotherthing);*/ +//! Compares orientations (more readable, user-friendly function) +PX_CUDA_CALLABLE PX_FORCE_INLINE bool sameDirection(const PxVec3& d, const PxVec3& p) +{ + return d.dot(p) >= 0.0f; +} + +//! Checks 2 values have different signs +PX_CUDA_CALLABLE PX_FORCE_INLINE IntBool differentSign(PxReal f0, PxReal f1) +{ +#if !PX_EMSCRIPTEN + union + { + PxU32 u; + PxReal f; + } u1, u2; + u1.f = f0; + u2.f = f1; + return IntBool((u1.u ^ u2.u) & PX_SIGN_BITMASK); +#else + // javascript floats are 64-bits... + return IntBool( (f0*f1) < 0.0f ); +#endif +} + +PX_CUDA_CALLABLE PX_FORCE_INLINE PxMat33 star(const PxVec3& v) +{ + return PxMat33(PxVec3(0, v.z, -v.y), PxVec3(-v.z, 0, v.x), PxVec3(v.y, -v.x, 0)); +} + +PX_CUDA_CALLABLE PX_INLINE PxVec3 log(const PxQuat& q) +{ + const PxReal s = q.getImaginaryPart().magnitude(); + if(s < 1e-12f) + return PxVec3(0.0f); + // force the half-angle to have magnitude <= pi/2 + PxReal halfAngle = q.w < 0 ? PxAtan2(-s, -q.w) : PxAtan2(s, q.w); + PX_ASSERT(halfAngle >= -PxPi / 2 && halfAngle <= PxPi / 2); + + return q.getImaginaryPart().getNormalized() * 2.f * halfAngle; +} + +PX_CUDA_CALLABLE PX_INLINE PxQuat exp(const PxVec3& v) +{ + const PxReal m = v.magnitudeSquared(); + return m < 1e-24f ? PxQuat(PxIdentity) : PxQuat(PxSqrt(m), v * PxRecipSqrt(m)); +} + +// quat to rotate v0 t0 v1 +PX_CUDA_CALLABLE PX_INLINE PxQuat rotationArc(const PxVec3& v0, const PxVec3& v1) +{ + const PxVec3 cross = v0.cross(v1); + const PxReal d = v0.dot(v1); + if(d <= -0.99999f) + return (PxAbs(v0.x) < 0.1f ? PxQuat(0.0f, v0.z, -v0.y, 0.0f) : PxQuat(v0.y, -v0.x, 0.0, 0.0)).getNormalized(); + + const PxReal s = PxSqrt((1 + d) * 2), r = 1 / s; + + return PxQuat(cross.x * r, cross.y * r, cross.z * r, s * 0.5f).getNormalized(); +} + +/** +\brief returns largest axis +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 largestAxis(const PxVec3& v) +{ + PxU32 m = PxU32(v.y > v.x ? 1 : 0); + return v.z > v[m] ? 2 : m; +} + +/** +\brief returns indices for the largest axis and 2 other axii +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 largestAxis(const PxVec3& v, PxU32& other1, PxU32& other2) +{ + if(v.x >= PxMax(v.y, v.z)) + { + other1 = 1; + other2 = 2; + return 0; + } + else if(v.y >= v.z) + { + other1 = 0; + other2 = 2; + return 1; + } + else + { + other1 = 0; + other2 = 1; + return 2; + } +} + +/** +\brief returns axis with smallest absolute value +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 closestAxis(const PxVec3& v) +{ + PxU32 m = PxU32(PxAbs(v.y) > PxAbs(v.x) ? 1 : 0); + return PxAbs(v.z) > PxAbs(v[m]) ? 2 : m; +} + +PX_CUDA_CALLABLE PX_INLINE PxU32 closestAxis(const PxVec3& v, PxU32& j, PxU32& k) +{ + // find largest 2D plane projection + const PxF32 absPx = PxAbs(v.x); + const PxF32 absNy = PxAbs(v.y); + const PxF32 absNz = PxAbs(v.z); + + PxU32 m = 0; // x biggest axis + j = 1; + k = 2; + if(absNy > absPx && absNy > absNz) + { + // y biggest + j = 2; + k = 0; + m = 1; + } + else if(absNz > absPx) + { + // z biggest + j = 0; + k = 1; + m = 2; + } + return m; +} + +/*! +Extend an edge along its length by a factor +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE void makeFatEdge(PxVec3& p0, PxVec3& p1, PxReal fatCoeff) +{ + PxVec3 delta = p1 - p0; + + const PxReal m = delta.magnitude(); + if(m > 0.0f) + { + delta *= fatCoeff / m; + p0 -= delta; + p1 += delta; + } +} + +//! Compute point as combination of barycentric coordinates +PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 +computeBarycentricPoint(const PxVec3& p0, const PxVec3& p1, const PxVec3& p2, PxReal u, PxReal v) +{ + // This seems to confuse the compiler... + // return (1.0f - u - v)*p0 + u*p1 + v*p2; + const PxF32 w = 1.0f - u - v; + return PxVec3(w * p0.x + u * p1.x + v * p2.x, w * p0.y + u * p1.y + v * p2.y, w * p0.z + u * p1.z + v * p2.z); +} + +// generates a pair of quaternions (swing, twist) such that in = swing * twist, with +// swing.x = 0 +// twist.y = twist.z = 0, and twist is a unit quat +PX_FORCE_INLINE void separateSwingTwist(const PxQuat& q, PxQuat& swing, PxQuat& twist) +{ + twist = q.x != 0.0f ? PxQuat(q.x, 0, 0, q.w).getNormalized() : PxQuat(PxIdentity); + swing = q * twist.getConjugate(); +} + +PX_FORCE_INLINE float computeSwingAngle(float swingYZ, float swingW) +{ + return 4.0f * PxAtan2(swingYZ, 1.0f + swingW); // tan (t/2) = sin(t)/(1+cos t), so this is the quarter angle +} + +// generate two tangent vectors to a given normal +PX_FORCE_INLINE void normalToTangents(const PxVec3& normal, PxVec3& tangent0, PxVec3& tangent1) +{ + tangent0 = PxAbs(normal.x) < 0.70710678f ? PxVec3(0, -normal.z, normal.y) : PxVec3(-normal.y, normal.x, 0); + tangent0.normalize(); + tangent1 = normal.cross(tangent0); +} + +/** +\brief computes a oriented bounding box around the scaled basis. +\param basis Input = skewed basis, Output = (normalized) orthogonal basis. +\return Bounding box extent. +*/ +PX_FOUNDATION_API PxVec3 optimizeBoundingBox(PxMat33& basis); + +PX_FOUNDATION_API PxQuat slerp(const PxReal t, const PxQuat& left, const PxQuat& right); + +PX_CUDA_CALLABLE PX_INLINE PxVec3 ellipseClamp(const PxVec3& point, const PxVec3& radii) +{ + // This function need to be implemented in the header file because + // it is included in a spu shader program. + + // finds the closest point on the ellipse to a given point + + // (p.y, p.z) is the input point + // (e.y, e.z) are the radii of the ellipse + + // lagrange multiplier method with Newton/Halley hybrid root-finder. + // see http://www.geometrictools.com/Documentation/DistancePointToEllipse2.pdf + // for proof of Newton step robustness and initial estimate. + // Halley converges much faster but sometimes overshoots - when that happens we take + // a newton step instead + + // converges in 1-2 iterations where D&C works well, and it's good with 4 iterations + // with any ellipse that isn't completely crazy + + const PxU32 MAX_ITERATIONS = 20; + const PxReal convergenceThreshold = 1e-4f; + + // iteration requires first quadrant but we recover generality later + + PxVec3 q(0, PxAbs(point.y), PxAbs(point.z)); + const PxReal tinyEps = 1e-6f; // very close to minor axis is numerically problematic but trivial + if(radii.y >= radii.z) + { + if(q.z < tinyEps) + return PxVec3(0, point.y > 0 ? radii.y : -radii.y, 0); + } + else + { + if(q.y < tinyEps) + return PxVec3(0, 0, point.z > 0 ? radii.z : -radii.z); + } + + PxVec3 denom, e2 = radii.multiply(radii), eq = radii.multiply(q); + + // we can use any initial guess which is > maximum(-e.y^2,-e.z^2) and for which f(t) is > 0. + // this guess works well near the axes, but is weak along the diagonals. + + PxReal t = PxMax(eq.y - e2.y, eq.z - e2.z); + + for(PxU32 i = 0; i < MAX_ITERATIONS; i++) + { + denom = PxVec3(0, 1 / (t + e2.y), 1 / (t + e2.z)); + PxVec3 denom2 = eq.multiply(denom); + + PxVec3 fv = denom2.multiply(denom2); + PxReal f = fv.y + fv.z - 1; + + // although in exact arithmetic we are guaranteed f>0, we can get here + // on the first iteration via catastrophic cancellation if the point is + // very close to the origin. In that case we just behave as if f=0 + + if(f < convergenceThreshold) + return e2.multiply(point).multiply(denom); + + PxReal df = fv.dot(denom) * -2.0f; + t = t - f / df; + } + + // we didn't converge, so clamp what we have + PxVec3 r = e2.multiply(point).multiply(denom); + return r * PxRecipSqrt(sqr(r.y / radii.y) + sqr(r.z / radii.z)); +} + +PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal tanHalf(PxReal sin, PxReal cos) +{ + // PT: avoids divide by zero for singularity. We return sqrt(FLT_MAX) instead of FLT_MAX + // to make sure the calling code doesn't generate INF values when manipulating the returned value + // (some joints multiply it by 4, etc). + if(cos==-1.0f) + return sin<0.0f ? -sqrtf(FLT_MAX) : sqrtf(FLT_MAX); + + // PT: half-angle formula: tan(a/2) = sin(a)/(1+cos(a)) + return sin / (1.0f + cos); +} + +PX_INLINE PxQuat quatFromTanQVector(const PxVec3& v) +{ + PxReal v2 = v.dot(v); + if(v2 < 1e-12f) + return PxQuat(PxIdentity); + PxReal d = 1 / (1 + v2); + return PxQuat(v.x * 2, v.y * 2, v.z * 2, 1 - v2) * d; +} + +PX_FORCE_INLINE PxVec3 cross100(const PxVec3& b) +{ + return PxVec3(0.0f, -b.z, b.y); +} +PX_FORCE_INLINE PxVec3 cross010(const PxVec3& b) +{ + return PxVec3(b.z, 0.0f, -b.x); +} +PX_FORCE_INLINE PxVec3 cross001(const PxVec3& b) +{ + return PxVec3(-b.y, b.x, 0.0f); +} + +PX_INLINE void decomposeVector(PxVec3& normalCompo, PxVec3& tangentCompo, const PxVec3& outwardDir, + const PxVec3& outwardNormal) +{ + normalCompo = outwardNormal * (outwardDir.dot(outwardNormal)); + tangentCompo = outwardDir - normalCompo; +} + +//! \brief Return (i+1)%3 +// Avoid variable shift for XBox: +// PX_INLINE PxU32 Ps::getNextIndex3(PxU32 i) { return (1<> 1)) & 3; +} + +PX_INLINE PxMat33 rotFrom2Vectors(const PxVec3& from, const PxVec3& to) +{ + // See bottom of http://www.euclideanspace.com/maths/algebra/matrix/orthogonal/rotation/index.htm + + // Early exit if to = from + if((from - to).magnitudeSquared() < 1e-4f) + return PxMat33(PxIdentity); + + // Early exit if to = -from + if((from + to).magnitudeSquared() < 1e-4f) + return PxMat33::createDiagonal(PxVec3(1.0f, -1.0f, -1.0f)); + + PxVec3 n = from.cross(to); + + PxReal C = from.dot(to), S = PxSqrt(1 - C * C), CC = 1 - C; + + PxReal xx = n.x * n.x, yy = n.y * n.y, zz = n.z * n.z, xy = n.x * n.y, yz = n.y * n.z, xz = n.x * n.z; + + PxMat33 R; + + R(0, 0) = 1 + CC * (xx - 1); + R(0, 1) = -n.z * S + CC * xy; + R(0, 2) = n.y * S + CC * xz; + + R(1, 0) = n.z * S + CC * xy; + R(1, 1) = 1 + CC * (yy - 1); + R(1, 2) = -n.x * S + CC * yz; + + R(2, 0) = -n.y * S + CC * xz; + R(2, 1) = n.x * S + CC * yz; + R(2, 2) = 1 + CC * (zz - 1); + + return R; +} + +PX_FOUNDATION_API void integrateTransform(const PxTransform& curTrans, const PxVec3& linvel, const PxVec3& angvel, + PxReal timeStep, PxTransform& result); + +PX_INLINE void computeBasis(const PxVec3& dir, PxVec3& right, PxVec3& up) +{ + // Derive two remaining vectors + if(PxAbs(dir.y) <= 0.9999f) + { + right = PxVec3(dir.z, 0.0f, -dir.x); + right.normalize(); + + // PT: normalize not needed for 'up' because dir & right are unit vectors, + // and by construction the angle between them is 90 degrees (i.e. sin(angle)=1) + up = PxVec3(dir.y * right.z, dir.z * right.x - dir.x * right.z, -dir.y * right.x); + } + else + { + right = PxVec3(1.0f, 0.0f, 0.0f); + + up = PxVec3(0.0f, dir.z, -dir.y); + up.normalize(); + } +} + +PX_INLINE void computeBasis(const PxVec3& p0, const PxVec3& p1, PxVec3& dir, PxVec3& right, PxVec3& up) +{ + // Compute the new direction vector + dir = p1 - p0; + dir.normalize(); + + // Derive two remaining vectors + computeBasis(dir, right, up); +} + +PX_FORCE_INLINE bool isAlmostZero(const PxVec3& v) +{ + if(PxAbs(v.x) > 1e-6f || PxAbs(v.y) > 1e-6f || PxAbs(v.z) > 1e-6f) + return false; + return true; +} + +} // namespace shdfnd +} // namespace physx + +#endif diff --git a/sources/PhysX/PhysX/source/foundation/include/PsMutex.h b/sources/PhysX/PhysX/source/foundation/include/PsMutex.h new file mode 100644 index 00000000..79949906 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsMutex.h @@ -0,0 +1,182 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSMUTEX_H +#define PSFOUNDATION_PSMUTEX_H + +#include "PsAllocator.h" + +/* + * This inclusion is a best known fix for gcc 4.4.1 error: + * Creating object file for apex/src/PsAllocator.cpp ... + * In file included from apex/include/PsFoundation.h:30, + * from apex/src/PsAllocator.cpp:26: + * apex/include/PsMutex.h: In constructor 'physx::shdfnd::MutexT::MutexT(const Alloc&)': + * apex/include/PsMutex.h:92: error: no matching function for call to 'operator new(unsigned int, + * physx::shdfnd::MutexImpl*&)' + * :0: note: candidates are: void* operator new(unsigned int) + */ +#include + +namespace physx +{ +namespace shdfnd +{ +class PX_FOUNDATION_API MutexImpl +{ + public: + /** + The constructor for Mutex creates a mutex. It is initially unlocked. + */ + MutexImpl(); + + /** + The destructor for Mutex deletes the mutex. + */ + ~MutexImpl(); + + /** + Acquire (lock) the mutex. If the mutex is already locked + by another thread, this method blocks until the mutex is + unlocked. + */ + void lock(); + + /** + Acquire (lock) the mutex. If the mutex is already locked + by another thread, this method returns false without blocking. + */ + bool trylock(); + + /** + Release (unlock) the mutex. + */ + void unlock(); + + /** + Size of this class. + */ + static uint32_t getSize(); +}; + +template > +class MutexT : protected Alloc +{ + PX_NOCOPY(MutexT) + public: + class ScopedLock + { + MutexT& mMutex; + PX_NOCOPY(ScopedLock) + public: + PX_INLINE ScopedLock(MutexT& mutex) : mMutex(mutex) + { + mMutex.lock(); + } + PX_INLINE ~ScopedLock() + { + mMutex.unlock(); + } + }; + + /** + The constructor for Mutex creates a mutex. It is initially unlocked. + */ + MutexT(const Alloc& alloc = Alloc()) : Alloc(alloc) + { + mImpl = reinterpret_cast(Alloc::allocate(MutexImpl::getSize(), __FILE__, __LINE__)); + PX_PLACEMENT_NEW(mImpl, MutexImpl)(); + } + + /** + The destructor for Mutex deletes the mutex. + */ + ~MutexT() + { + mImpl->~MutexImpl(); + Alloc::deallocate(mImpl); + } + + /** + Acquire (lock) the mutex. If the mutex is already locked + by another thread, this method blocks until the mutex is + unlocked. + */ + void lock() const + { + mImpl->lock(); + } + + /** + Acquire (lock) the mutex. If the mutex is already locked + by another thread, this method returns false without blocking, + returns true if lock is successfully acquired + */ + bool trylock() const + { + return mImpl->trylock(); + } + + /** + Release (unlock) the mutex, the calling thread must have + previously called lock() or method will error + */ + void unlock() const + { + mImpl->unlock(); + } + + private: + MutexImpl* mImpl; +}; + +class PX_FOUNDATION_API ReadWriteLock +{ + PX_NOCOPY(ReadWriteLock) + public: + ReadWriteLock(); + ~ReadWriteLock(); + + // "takeLock" can only be false if the thread already holds the mutex, e.g. if it already acquired the write lock + void lockReader(bool takeLock); + void lockWriter(); + + void unlockReader(); + void unlockWriter(); + + private: + class ReadWriteLockImpl* mImpl; +}; + +typedef MutexT<> Mutex; + +} // namespace shdfnd +} // namespace physx + +#endif // #ifndef PSFOUNDATION_PSMUTEX_H diff --git a/sources/PhysX/PhysX/source/foundation/include/PsPool.h b/sources/PhysX/PhysX/source/foundation/include/PsPool.h new file mode 100644 index 00000000..d4f5f20f --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsPool.h @@ -0,0 +1,298 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSPOOL_H +#define PSFOUNDATION_PSPOOL_H + +#include "PsArray.h" +#include "PsSort.h" +#include "PsBasicTemplates.h" +#include "PsInlineArray.h" + +namespace physx +{ +namespace shdfnd +{ + +/*! +Simple allocation pool +*/ +template ::Type> +class PoolBase : public UserAllocated, public Alloc +{ + PX_NOCOPY(PoolBase) + protected: + PoolBase(const Alloc& alloc, uint32_t elementsPerSlab, uint32_t slabSize) + : Alloc(alloc), mSlabs(alloc), mElementsPerSlab(elementsPerSlab), mUsed(0), mSlabSize(slabSize), mFreeElement(0) + { + PX_COMPILE_TIME_ASSERT(sizeof(T) >= sizeof(size_t)); + } + + public: + ~PoolBase() + { + if(mUsed) + disposeElements(); + + for(void** slabIt = mSlabs.begin(), *slabEnd = mSlabs.end(); slabIt != slabEnd; ++slabIt) + Alloc::deallocate(*slabIt); + } + + // Allocate space for single object + PX_INLINE T* allocate() + { + if(mFreeElement == 0) + allocateSlab(); + T* p = reinterpret_cast(mFreeElement); + mFreeElement = mFreeElement->mNext; + mUsed++; +/** +Mark a specified amount of memory with 0xcd pattern. This is used to check that the meta data +definition for serialized classes is complete in checked builds. +*/ +#if PX_CHECKED + for(uint32_t i = 0; i < sizeof(T); ++i) + reinterpret_cast(p)[i] = 0xcd; +#endif + return p; + } + + // Put space for a single element back in the lists + PX_INLINE void deallocate(T* p) + { + if(p) + { + PX_ASSERT(mUsed); + mUsed--; + push(reinterpret_cast(p)); + } + } + + PX_INLINE T* construct() + { + T* t = allocate(); + return t ? new (t) T() : 0; + } + + template + PX_INLINE T* construct(A1& a) + { + T* t = allocate(); + return t ? new (t) T(a) : 0; + } + + template + PX_INLINE T* construct(A1& a, A2& b) + { + T* t = allocate(); + return t ? new (t) T(a, b) : 0; + } + + template + PX_INLINE T* construct(A1& a, A2& b, A3& c) + { + T* t = allocate(); + return t ? new (t) T(a, b, c) : 0; + } + + template + PX_INLINE T* construct(A1* a, A2& b, A3& c) + { + T* t = allocate(); + return t ? new (t) T(a, b, c) : 0; + } + + template + PX_INLINE T* construct(A1& a, A2& b, A3& c, A4& d) + { + T* t = allocate(); + return t ? new (t) T(a, b, c, d) : 0; + } + + template + PX_INLINE T* construct(A1& a, A2& b, A3& c, A4& d, A5& e) + { + T* t = allocate(); + return t ? new (t) T(a, b, c, d, e) : 0; + } + + PX_INLINE void destroy(T* const p) + { + if(p) + { + p->~T(); + deallocate(p); + } + } + + protected: + struct FreeList + { + FreeList* mNext; + }; + + // All the allocated slabs, sorted by pointer + InlineArray mSlabs; + + uint32_t mElementsPerSlab; + uint32_t mUsed; + uint32_t mSlabSize; + + FreeList* mFreeElement; // Head of free-list + + // Helper function to get bitmap of allocated elements + + void push(FreeList* p) + { + p->mNext = mFreeElement; + mFreeElement = p; + } + + // Allocate a slab and segregate it into the freelist + void allocateSlab() + { + T* slab = reinterpret_cast(Alloc::allocate(mSlabSize, __FILE__, __LINE__)); + + mSlabs.pushBack(slab); + + // Build a chain of nodes for the freelist + T* it = slab + mElementsPerSlab; + while(--it >= slab) + push(reinterpret_cast(it)); + } + + /* + Cleanup method. Go through all active slabs and call destructor for live objects, + then free their memory + */ + void disposeElements() + { + Array freeNodes(*this); + while(mFreeElement) + { + freeNodes.pushBack(mFreeElement); + mFreeElement = mFreeElement->mNext; + } + Alloc& alloc(*this); + sort(freeNodes.begin(), freeNodes.size(), Less(), alloc); + sort(mSlabs.begin(), mSlabs.size(), Less(), alloc); + + typename Array::Iterator slabIt = mSlabs.begin(), slabEnd = mSlabs.end(); + for(typename Array::Iterator freeIt = freeNodes.begin(); slabIt != slabEnd; ++slabIt) + { + for(T* tIt = reinterpret_cast(*slabIt), *tEnd = tIt + mElementsPerSlab; tIt != tEnd; ++tIt) + { + if(freeIt != freeNodes.end() && *freeIt == tIt) + ++freeIt; + else + tIt->~T(); + } + } + } + + /* + Go through all slabs and call destructor if the slab is empty + */ + void releaseEmptySlabs() + { + Array freeNodes(*this); + Array slabNodes(mSlabs, *this); + while(mFreeElement) + { + freeNodes.pushBack(mFreeElement); + mFreeElement = mFreeElement->mNext; + } + + typename Array::Iterator freeIt = freeNodes.begin(), freeEnd = freeNodes.end(), + lastCheck = freeNodes.end() - mElementsPerSlab; + + if(freeNodes.size() > mElementsPerSlab) + { + Alloc& alloc(*this); + sort(freeNodes.begin(), freeNodes.size(), Less(), alloc); + sort(slabNodes.begin(), slabNodes.size(), Less(), alloc); + + mSlabs.clear(); + for(void** slabIt = slabNodes.begin(), *slabEnd = slabNodes.end(); slabIt != slabEnd; ++slabIt) + { + while((freeIt < lastCheck) && (*slabIt > (*freeIt))) + { + push(reinterpret_cast(*freeIt)); + freeIt++; + } + + if(*slabIt == (*freeIt)) // the slab's first element in freeList + { + const size_t endSlabAddress = size_t(*slabIt) + mSlabSize; + const size_t endFreeAddress = size_t(*(freeIt + mElementsPerSlab - 1)); + if(endFreeAddress + sizeof(T) == endSlabAddress) + { // all slab's element in freeList + Alloc::deallocate(*slabIt); + freeIt += mElementsPerSlab; + continue; + } + } + + mSlabs.pushBack(*slabIt); + } + } + + while(freeIt != freeEnd) + { + push(reinterpret_cast(*freeIt)); + ++freeIt; + } + } +}; + +// original pool implementation +template ::Type> +class Pool : public PoolBase +{ + public: + Pool(const Alloc& alloc = Alloc(), uint32_t elementsPerSlab = 32) + : PoolBase(alloc, elementsPerSlab, elementsPerSlab * sizeof(T)) + { + } +}; + +// allows specification of the slab size instead of the occupancy +template ::Type> +class Pool2 : public PoolBase +{ + public: + Pool2(const Alloc& alloc = Alloc()) : PoolBase(alloc, slabSize / sizeof(T), slabSize) + { + } +}; + +} // namespace shdfnd +} // namespace physx + +#endif // #ifndef PSFOUNDATION_PSPOOL_H diff --git a/sources/PhysX/PhysX/source/foundation/include/PsSList.h b/sources/PhysX/PhysX/source/foundation/include/PsSList.h new file mode 100644 index 00000000..aab971b7 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsSList.h @@ -0,0 +1,140 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSSLIST_H +#define PSFOUNDATION_PSSLIST_H + +#include "foundation/Px.h" +#include "foundation/PxAssert.h" +#include "PsAlignedMalloc.h" + +#if PX_P64_FAMILY +#define PX_SLIST_ALIGNMENT 16 +#else +#define PX_SLIST_ALIGNMENT 8 +#endif + +namespace physx +{ +namespace shdfnd +{ + +#if PX_VC +#pragma warning(push) +#pragma warning(disable : 4324) // Padding was added at the end of a structure because of a __declspec(align) value. +#endif + +#if !PX_GCC_FAMILY +__declspec(align(PX_SLIST_ALIGNMENT)) +#endif + class SListEntry +{ + friend struct SListImpl; + + public: + SListEntry() : mNext(NULL) + { + PX_ASSERT((size_t(this) & (PX_SLIST_ALIGNMENT - 1)) == 0); + } + + // Only use on elements returned by SList::flush() + // because the operation is not atomic. + SListEntry* next() + { + return mNext; + } + + private: + SListEntry* mNext; +} +#if PX_GCC_FAMILY +__attribute__((aligned(PX_SLIST_ALIGNMENT))); +#else +; +#endif + +#if PX_VC +#pragma warning(pop) +#endif + +// template-less implementation +struct PX_FOUNDATION_API SListImpl +{ + SListImpl(); + ~SListImpl(); + void push(SListEntry* entry); + SListEntry* pop(); + SListEntry* flush(); + static uint32_t getSize(); +}; + +template > +class SListT : protected Alloc +{ + public: + SListT(const Alloc& alloc = Alloc()) : Alloc(alloc) + { + mImpl = reinterpret_cast(Alloc::allocate(SListImpl::getSize(), __FILE__, __LINE__)); + PX_ASSERT((size_t(mImpl) & (PX_SLIST_ALIGNMENT - 1)) == 0); + PX_PLACEMENT_NEW(mImpl, SListImpl)(); + } + ~SListT() + { + mImpl->~SListImpl(); + Alloc::deallocate(mImpl); + } + + // pushes a new element to the list + void push(SListEntry& entry) + { + mImpl->push(&entry); + } + + // pops an element from the list + SListEntry* pop() + { + return mImpl->pop(); + } + + // removes all items from list, returns pointer to first element + SListEntry* flush() + { + return mImpl->flush(); + } + + private: + SListImpl* mImpl; +}; + +typedef SListT<> SList; + +} // namespace shdfnd +} // namespace physx + +#endif // #ifndef PSFOUNDATION_PSSLIST_H diff --git a/sources/PhysX/PhysX/source/foundation/include/PsSocket.h b/sources/PhysX/PhysX/source/foundation/include/PsSocket.h new file mode 100644 index 00000000..75cd2ef5 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsSocket.h @@ -0,0 +1,186 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSSOCKET_H +#define PSFOUNDATION_PSSOCKET_H + +#include "PsUserAllocated.h" + +namespace physx +{ +namespace shdfnd +{ +/** +Socket abstraction API +*/ + +class PX_FOUNDATION_API Socket : public UserAllocated +{ + public: + static const uint32_t DEFAULT_BUFFER_SIZE; + + Socket(bool inEnableBuffering = true, bool blocking = true); + + virtual ~Socket(); + + /*! + Opens a network socket for input and/or output + + \param host + Name of the host to connect to. This can be an IP, URL, etc + + \param port + The port to connect to on the remote host + + \param timeout + Timeout in ms until the connection must be established. + + \return + True if the connection was successful, false otherwise + */ + bool connect(const char* host, uint16_t port, uint32_t timeout = 1000); + + /*! + Opens a network socket for input and/or output as a server. Put the connection in listening mode + + \param port + The port on which the socket listens + */ + bool listen(uint16_t port); + + /*! + Accept a connection on a socket that is in listening mode + + \note + This method only supports a single connection client. Additional clients + that connect to the listening port will overwrite the existing socket handle. + + \param block + whether or not the call should block + + \return whether a connection was established + */ + bool accept(bool block); + + /*! + Disconnects an open socket + */ + void disconnect(); + + /*! + Returns whether the socket is currently open (connected) or not. + + \return + True if the socket is connected, false otherwise + */ + bool isConnected() const; + + /*! + Returns the name of the connected host. This is the same as the string + that was supplied to the connect call. + + \return + The name of the connected host + */ + const char* getHost() const; + + /*! + Returns the port of the connected host. This is the same as the port + that was supplied to the connect call. + + \return + The port of the connected host + */ + uint16_t getPort() const; + + /*! + Flushes the output stream. Until the stream is flushed, there is no + guarantee that the written data has actually reached the destination + storage. Flush forces all buffered data to be sent to the output. + + \note flush always blocks. If the socket is in non-blocking mode, this will result + the thread spinning. + + \return + True if the flush was successful, false otherwise + */ + bool flush(); + + /*! + Writes data to the output stream. + + \param data + Pointer to a block of data to write to the stream + + \param length + Amount of data to write, in bytes + + \return + Number of bytes actually written. This could be lower than length if the socket is non-blocking. + */ + + uint32_t write(const uint8_t* data, uint32_t length); + + /*! + Reads data from the output stream. + + \param data + Pointer to a buffer where the read data will be stored. + + \param length + Amount of data to read, in bytes. + + \return + Number of bytes actually read. This could be lower than length if the stream end is + encountered or the socket is non-blocking. + */ + uint32_t read(uint8_t* data, uint32_t length); + + /*! + Sets blocking mode of the socket. + Socket must be connected, otherwise calling this method won't take any effect. + */ + void setBlocking(bool blocking); + + /*! + Returns whether read/write/flush calls to the socket are blocking. + + \return + True if the socket is blocking. + */ + bool isBlocking() const; + + private: + class SocketImpl* mImpl; +}; + +} // namespace shdfnd +} // namespace physx + +#endif // PSFOUNDATION_PSSOCKET_H diff --git a/sources/PhysX/PhysX/source/foundation/include/PsSort.h b/sources/PhysX/PhysX/source/foundation/include/PsSort.h new file mode 100644 index 00000000..1b7b4f72 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsSort.h @@ -0,0 +1,130 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSSORT_H +#define PSFOUNDATION_PSSORT_H + +/** \addtogroup foundation +@{ +*/ + +#include "PsSortInternals.h" +#include "PsAlloca.h" + +#define PX_SORT_PARANOIA PX_DEBUG + +/** +\brief Sorts an array of objects in ascending order, assuming +that the predicate implements the < operator: + +\see Less, Greater +*/ + +#if PX_VC +#pragma warning(push) +#pragma warning(disable : 4706) // disable the warning that we did an assignment within a conditional expression, as +// this was intentional. +#endif + +namespace physx +{ +namespace shdfnd +{ +template +void sort(T* elements, uint32_t count, const Predicate& compare, const Allocator& inAllocator, + const uint32_t initialStackSize = 32) +{ + static const uint32_t SMALL_SORT_CUTOFF = 5; // must be >= 3 since we need 3 for median + + PX_ALLOCA(stackMem, int32_t, initialStackSize); + internal::Stack stack(stackMem, initialStackSize, inAllocator); + + int32_t first = 0, last = int32_t(count - 1); + if(last > first) + { + for(;;) + { + while(last > first) + { + PX_ASSERT(first >= 0 && last < int32_t(count)); + if(uint32_t(last - first) < SMALL_SORT_CUTOFF) + { + internal::smallSort(elements, first, last, compare); + break; + } + else + { + const int32_t partIndex = internal::partition(elements, first, last, compare); + + // push smaller sublist to minimize stack usage + if((partIndex - first) < (last - partIndex)) + { + stack.push(first, partIndex - 1); + first = partIndex + 1; + } + else + { + stack.push(partIndex + 1, last); + last = partIndex - 1; + } + } + } + + if(stack.empty()) + break; + + stack.pop(first, last); + } + } +#if PX_SORT_PARANOIA + for(uint32_t i = 1; i < count; i++) + PX_ASSERT(!compare(elements[i], elements[i - 1])); +#endif +} + +template +void sort(T* elements, uint32_t count, const Predicate& compare) +{ + sort(elements, count, compare, typename shdfnd::AllocatorTraits::Type()); +} + +template +void sort(T* elements, uint32_t count) +{ + sort(elements, count, shdfnd::Less(), typename shdfnd::AllocatorTraits::Type()); +} + +} // namespace shdfnd +} // namespace physx + +#if PX_VC +#pragma warning(pop) +#endif + +#endif // #ifndef PSFOUNDATION_PSSORT_H diff --git a/sources/PhysX/PhysX/source/foundation/include/PsSortInternals.h b/sources/PhysX/PhysX/source/foundation/include/PsSortInternals.h new file mode 100644 index 00000000..72b3857c --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsSortInternals.h @@ -0,0 +1,188 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSSORTINTERNALS_H +#define PSFOUNDATION_PSSORTINTERNALS_H + +/** \addtogroup foundation +@{ +*/ + +#include "foundation/PxAssert.h" +#include "foundation/PxIntrinsics.h" +#include "PsBasicTemplates.h" +#include "PsUserAllocated.h" + +namespace physx +{ +namespace shdfnd +{ +namespace internal +{ +template +PX_INLINE void median3(T* elements, int32_t first, int32_t last, Predicate& compare) +{ + /* + This creates sentinels because we know there is an element at the start minimum(or equal) + than the pivot and an element at the end greater(or equal) than the pivot. Plus the + median of 3 reduces the chance of degenerate behavour. + */ + + int32_t mid = (first + last) / 2; + + if(compare(elements[mid], elements[first])) + swap(elements[first], elements[mid]); + + if(compare(elements[last], elements[first])) + swap(elements[first], elements[last]); + + if(compare(elements[last], elements[mid])) + swap(elements[mid], elements[last]); + + // keep the pivot at last-1 + swap(elements[mid], elements[last - 1]); +} + +template +PX_INLINE int32_t partition(T* elements, int32_t first, int32_t last, Predicate& compare) +{ + median3(elements, first, last, compare); + + /* + WARNING: using the line: + + T partValue = elements[last-1]; + + and changing the scan loops to: + + while(comparator.greater(partValue, elements[++i])); + while(comparator.greater(elements[--j], partValue); + + triggers a compiler optimizer bug on xenon where it stores a double to the stack for partValue + then loads it as a single...:-( + */ + + int32_t i = first; // we know first is less than pivot(but i gets pre incremented) + int32_t j = last - 1; // pivot is in last-1 (but j gets pre decremented) + + for(;;) + { + while(compare(elements[++i], elements[last - 1])) + ; + while(compare(elements[last - 1], elements[--j])) + ; + + if(i >= j) + break; + + PX_ASSERT(i <= last && j >= first); + swap(elements[i], elements[j]); + } + // put the pivot in place + + PX_ASSERT(i <= last && first <= (last - 1)); + swap(elements[i], elements[last - 1]); + + return i; +} + +template +PX_INLINE void smallSort(T* elements, int32_t first, int32_t last, Predicate& compare) +{ + // selection sort - could reduce to fsel on 360 with floats. + + for(int32_t i = first; i < last; i++) + { + int32_t m = i; + for(int32_t j = i + 1; j <= last; j++) + if(compare(elements[j], elements[m])) + m = j; + + if(m != i) + swap(elements[m], elements[i]); + } +} + +template +class Stack +{ + Allocator mAllocator; + uint32_t mSize, mCapacity; + int32_t* mMemory; + bool mRealloc; + + public: + Stack(int32_t* memory, uint32_t capacity, const Allocator& inAllocator) + : mAllocator(inAllocator), mSize(0), mCapacity(capacity), mMemory(memory), mRealloc(false) + { + } + ~Stack() + { + if(mRealloc) + mAllocator.deallocate(mMemory); + } + + void grow() + { + mCapacity *= 2; + int32_t* newMem = + reinterpret_cast(mAllocator.allocate(sizeof(int32_t) * mCapacity, __FILE__, __LINE__)); + intrinsics::memCopy(newMem, mMemory, mSize * sizeof(int32_t)); + if(mRealloc) + mAllocator.deallocate(mMemory); + mRealloc = true; + mMemory = newMem; + } + + PX_INLINE void push(int32_t start, int32_t end) + { + if(mSize >= mCapacity - 1) + grow(); + mMemory[mSize++] = start; + mMemory[mSize++] = end; + } + + PX_INLINE void pop(int32_t& start, int32_t& end) + { + PX_ASSERT(!empty()); + end = mMemory[--mSize]; + start = mMemory[--mSize]; + } + + PX_INLINE bool empty() + { + return mSize == 0; + } +}; +} // namespace internal + +} // namespace shdfnd +} // namespace physx + +#endif // #ifndef PSFOUNDATION_PSSORTINTERNALS_H diff --git a/sources/PhysX/PhysX/source/foundation/include/PsString.h b/sources/PhysX/PhysX/source/foundation/include/PsString.h new file mode 100644 index 00000000..6010fde0 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsString.h @@ -0,0 +1,91 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSSTRING_H +#define PSFOUNDATION_PSSTRING_H + +#include "foundation/PxPreprocessor.h" +#include "foundation/PxSimpleTypes.h" +#include "foundation/PxFoundationConfig.h" +#include + +namespace physx +{ +namespace shdfnd +{ + +// the following functions have C99 semantics. Note that C99 requires for snprintf and vsnprintf: +// * the resulting string is always NULL-terminated regardless of truncation. +// * in the case of truncation the return value is the number of characters that would have been created. + +PX_FOUNDATION_API int32_t sscanf(const char* buffer, const char* format, ...); +PX_FOUNDATION_API int32_t strcmp(const char* str1, const char* str2); +PX_FOUNDATION_API int32_t strncmp(const char* str1, const char* str2, size_t count); +PX_FOUNDATION_API int32_t snprintf(char* dst, size_t dstSize, const char* format, ...); +PX_FOUNDATION_API int32_t vsnprintf(char* dst, size_t dstSize, const char* src, va_list arg); + +// strlcat and strlcpy have BSD semantics: +// * dstSize is always the size of the destination buffer +// * the resulting string is always NULL-terminated regardless of truncation +// * in the case of truncation the return value is the length of the string that would have been created + +PX_FOUNDATION_API size_t strlcat(char* dst, size_t dstSize, const char* src); +PX_FOUNDATION_API size_t strlcpy(char* dst, size_t dstSize, const char* src); + +// case-insensitive string comparison +PX_FOUNDATION_API int32_t stricmp(const char* str1, const char* str2); +PX_FOUNDATION_API int32_t strnicmp(const char* str1, const char* str2, size_t count); + +// in-place string case conversion +PX_FOUNDATION_API void strlwr(char* str); +PX_FOUNDATION_API void strupr(char* str); + +/** +\brief The maximum supported formatted output string length +(number of characters after replacement). + +@see printFormatted() +*/ +static const size_t MAX_PRINTFORMATTED_LENGTH = 1024; + +/** +\brief Prints the formatted data, trying to make sure it's visible to the app programmer + +@see NS_MAX_PRINTFORMATTED_LENGTH +*/ +PX_FOUNDATION_API void printFormatted(const char*, ...); + +/** +\brief Prints the string literally (does not consume % specifier), trying to make sure it's visible to the app +programmer +*/ +PX_FOUNDATION_API void printString(const char*); +} +} +#endif // #ifndef PSFOUNDATION_PSSTRING_H diff --git a/sources/PhysX/PhysX/source/foundation/include/PsSync.h b/sources/PhysX/PhysX/source/foundation/include/PsSync.h new file mode 100644 index 00000000..0fd87c2d --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsSync.h @@ -0,0 +1,138 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSSYNC_H +#define PSFOUNDATION_PSSYNC_H + +#include "PsAllocator.h" + +namespace physx +{ +namespace shdfnd +{ +/*! +Implementation notes: +* - Calling set() on an already signaled Sync does not change its state. +* - Calling reset() on an already reset Sync does not change its state. +* - Calling set() on a reset Sync wakes all waiting threads (potential for thread contention). +* - Calling wait() on an already signaled Sync will return true immediately. +* - NOTE: be careful when pulsing an event with set() followed by reset(), because a +* thread that is not waiting on the event will miss the signal. +*/ +class PX_FOUNDATION_API SyncImpl +{ + public: + static const uint32_t waitForever = 0xffffffff; + + SyncImpl(); + + ~SyncImpl(); + + /** Wait on the object for at most the given number of ms. Returns + * true if the object is signaled. Sync::waitForever will block forever + * or until the object is signaled. + */ + + bool wait(uint32_t milliseconds = waitForever); + + /** Signal the synchronization object, waking all threads waiting on it */ + + void set(); + + /** Reset the synchronization object */ + + void reset(); + + /** + Size of this class. + */ + static uint32_t getSize(); +}; + +/*! +Implementation notes: +* - Calling set() on an already signaled Sync does not change its state. +* - Calling reset() on an already reset Sync does not change its state. +* - Calling set() on a reset Sync wakes all waiting threads (potential for thread contention). +* - Calling wait() on an already signaled Sync will return true immediately. +* - NOTE: be careful when pulsing an event with set() followed by reset(), because a +* thread that is not waiting on the event will miss the signal. +*/ +template > +class SyncT : protected Alloc +{ + public: + static const uint32_t waitForever = SyncImpl::waitForever; + + SyncT(const Alloc& alloc = Alloc()) : Alloc(alloc) + { + mImpl = reinterpret_cast(Alloc::allocate(SyncImpl::getSize(), __FILE__, __LINE__)); + PX_PLACEMENT_NEW(mImpl, SyncImpl)(); + } + + ~SyncT() + { + mImpl->~SyncImpl(); + Alloc::deallocate(mImpl); + } + + /** Wait on the object for at most the given number of ms. Returns + * true if the object is signaled. Sync::waitForever will block forever + * or until the object is signaled. + */ + + bool wait(uint32_t milliseconds = SyncImpl::waitForever) + { + return mImpl->wait(milliseconds); + } + + /** Signal the synchronization object, waking all threads waiting on it */ + + void set() + { + mImpl->set(); + } + + /** Reset the synchronization object */ + + void reset() + { + mImpl->reset(); + } + + private: + class SyncImpl* mImpl; +}; + +typedef SyncT<> Sync; + +} // namespace shdfnd +} // namespace physx + +#endif // #ifndef PSFOUNDATION_PSSYNC_H diff --git a/sources/PhysX/PhysX/source/foundation/include/PsTempAllocator.h b/sources/PhysX/PhysX/source/foundation/include/PsTempAllocator.h new file mode 100644 index 00000000..10c0ceda --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsTempAllocator.h @@ -0,0 +1,62 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSTEMPALLOCATOR_H +#define PSFOUNDATION_PSTEMPALLOCATOR_H + +#include "PsAllocator.h" + +namespace physx +{ +namespace shdfnd +{ +union TempAllocatorChunk +{ + TempAllocatorChunk() : mNext(0) + { + } + TempAllocatorChunk* mNext; // while chunk is free + uint32_t mIndex; // while chunk is allocated + uint8_t mPad[16]; // 16 byte aligned allocations +}; + +class TempAllocator +{ + public: + PX_FORCE_INLINE TempAllocator(const char* = 0) + { + } + PX_FOUNDATION_API void* allocate(size_t size, const char* file, int line); + PX_FOUNDATION_API void deallocate(void* ptr); +}; + +} // namespace shdfnd +} // namespace physx + +#endif // #ifndef PSFOUNDATION_PSTEMPALLOCATOR_H diff --git a/sources/PhysX/PhysX/source/foundation/include/PsThread.h b/sources/PhysX/PhysX/source/foundation/include/PsThread.h new file mode 100644 index 00000000..1a6c5cc7 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsThread.h @@ -0,0 +1,384 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSTHREAD_H +#define PSFOUNDATION_PSTHREAD_H + +#include "PsUserAllocated.h" + +// dsequeira: according to existing comment here (David Black would be my guess) +// "This is useful to reduce bus contention on tight spin locks. And it needs +// to be a macro as the xenon compiler often ignores even __forceinline." What's not +// clear is why a pause function needs inlining...? (TODO: check with XBox team) + +// todo: these need to go somewhere else + +#if PX_WINDOWS_FAMILY || PX_XBOXONE +#define PxSpinLockPause() __asm pause +#elif PX_LINUX || PX_ANDROID || PX_PS4 || PX_APPLE_FAMILY || PX_SWITCH +#define PxSpinLockPause() asm("nop") +#else +#error "Platform not supported!" +#endif + +namespace physx +{ +namespace shdfnd +{ +struct ThreadPriority // todo: put in some other header file +{ + enum Enum + { + /** + \brief High priority + */ + eHIGH = 0, + + /** + \brief Above Normal priority + */ + eABOVE_NORMAL = 1, + + /** + \brief Normal/default priority + */ + eNORMAL = 2, + + /** + \brief Below Normal priority + */ + eBELOW_NORMAL = 3, + + /** + \brief Low priority. + */ + eLOW = 4, + eFORCE_DWORD = 0xffFFffFF + }; +}; + +class Runnable +{ + public: + Runnable() + { + } + virtual ~Runnable() + { + } + virtual void execute(void) + { + } +}; + +class PX_FOUNDATION_API ThreadImpl +{ + public: + typedef size_t Id; // space for a pointer or an integer + typedef void* (*ExecuteFn)(void*); + + static uint32_t getDefaultStackSize(); + static Id getId(); + + /** + Construct (but do not start) the thread object. The OS thread object will not be created + until start() is called. Executes in the context + of the spawning thread. + */ + + ThreadImpl(); + + /** + Construct and start the the thread, passing the given arg to the given fn. (pthread style) + */ + + ThreadImpl(ExecuteFn fn, void* arg, const char* name); + + /** + Deallocate all resources associated with the thread. Should be called in the + context of the spawning thread. + */ + + ~ThreadImpl(); + + /** + Create the OS thread and start it running. Called in the context of the spawning thread. + If an affinity mask has previously been set then it will be applied after the + thread has been created. + */ + + void start(uint32_t stackSize, Runnable* r); + + /** + Violently kill the current thread. Blunt instrument, not recommended since + it can leave all kinds of things unreleased (stack, memory, mutexes...) Should + be called in the context of the spawning thread. + */ + + void kill(); + + /** + Stop the thread. Signals the spawned thread that it should stop, so the + thread should check regularly + */ + + void signalQuit(); + + /** + Wait for a thread to stop. Should be called in the context of the spawning + thread. Returns false if the thread has not been started. + */ + + bool waitForQuit(); + + /** + check whether the thread is signalled to quit. Called in the context of the + spawned thread. + */ + + bool quitIsSignalled(); + + /** + Cleanly shut down this thread. Called in the context of the spawned thread. + */ + void quit(); + + /** + Change the affinity mask for this thread. The mask is a platform + specific value. + + On Windows, Linux, PS4, XboxOne and Switch platforms, each set mask bit represents + the index of a logical processor that the OS may schedule thread execution on. + Bits outside the range of valid logical processors may be ignored or cause + the function to return an error. + + On Apple platforms, this function has no effect. + + If the thread has not yet been started then the mask is stored + and applied when the thread is started. + + If the thread has already been started then this method returns the + previous affinity mask on success, otherwise it returns zero. + */ + uint32_t setAffinityMask(uint32_t mask); + + static ThreadPriority::Enum getPriority(Id threadId); + + /** Set thread priority. */ + void setPriority(ThreadPriority::Enum prio); + + /** set the thread's name */ + void setName(const char* name); + + /** Put the current thread to sleep for the given number of milliseconds */ + static void sleep(uint32_t ms); + + /** Yield the current thread's slot on the CPU */ + static void yield(); + + /** Return the number of physical cores (does not include hyper-threaded cores), returns 0 on failure */ + static uint32_t getNbPhysicalCores(); + + /** + Size of this class. + */ + static uint32_t getSize(); +}; + +/** +Thread abstraction API +*/ +template > +class ThreadT : protected Alloc, public UserAllocated, public Runnable +{ + public: + typedef ThreadImpl::Id Id; // space for a pointer or an integer + + /** + Construct (but do not start) the thread object. Executes in the context + of the spawning thread + */ + ThreadT(const Alloc& alloc = Alloc()) : Alloc(alloc) + { + mImpl = reinterpret_cast(Alloc::allocate(ThreadImpl::getSize(), __FILE__, __LINE__)); + PX_PLACEMENT_NEW(mImpl, ThreadImpl)(); + } + + /** + Construct and start the the thread, passing the given arg to the given fn. (pthread style) + */ + ThreadT(ThreadImpl::ExecuteFn fn, void* arg, const char* name, const Alloc& alloc = Alloc()) : Alloc(alloc) + { + mImpl = reinterpret_cast(Alloc::allocate(ThreadImpl::getSize(), __FILE__, __LINE__)); + PX_PLACEMENT_NEW(mImpl, ThreadImpl)(fn, arg, name); + } + + /** + Deallocate all resources associated with the thread. Should be called in the + context of the spawning thread. + */ + virtual ~ThreadT() + { + mImpl->~ThreadImpl(); + Alloc::deallocate(mImpl); + } + + /** + start the thread running. Called in the context of the spawning thread. + */ + + void start(uint32_t stackSize = ThreadImpl::getDefaultStackSize()) + { + mImpl->start(stackSize, this); + } + + /** + Violently kill the current thread. Blunt instrument, not recommended since + it can leave all kinds of things unreleased (stack, memory, mutexes...) Should + be called in the context of the spawning thread. + */ + + void kill() + { + mImpl->kill(); + } + + /** + The virtual execute() method is the user defined function that will + run in the new thread. Called in the context of the spawned thread. + */ + + virtual void execute(void) + { + } + + /** + stop the thread. Signals the spawned thread that it should stop, so the + thread should check regularly + */ + + void signalQuit() + { + mImpl->signalQuit(); + } + + /** + Wait for a thread to stop. Should be called in the context of the spawning + thread. Returns false if the thread has not been started. + */ + + bool waitForQuit() + { + return mImpl->waitForQuit(); + } + + /** + check whether the thread is signalled to quit. Called in the context of the + spawned thread. + */ + + bool quitIsSignalled() + { + return mImpl->quitIsSignalled(); + } + + /** + Cleanly shut down this thread. Called in the context of the spawned thread. + */ + void quit() + { + mImpl->quit(); + } + + uint32_t setAffinityMask(uint32_t mask) + { + return mImpl->setAffinityMask(mask); + } + + static ThreadPriority::Enum getPriority(ThreadImpl::Id threadId) + { + return ThreadImpl::getPriority(threadId); + } + + /** Set thread priority. */ + void setPriority(ThreadPriority::Enum prio) + { + mImpl->setPriority(prio); + } + + /** set the thread's name */ + void setName(const char* name) + { + mImpl->setName(name); + } + + /** Put the current thread to sleep for the given number of milliseconds */ + static void sleep(uint32_t ms) + { + ThreadImpl::sleep(ms); + } + + /** Yield the current thread's slot on the CPU */ + static void yield() + { + ThreadImpl::yield(); + } + + static uint32_t getDefaultStackSize() + { + return ThreadImpl::getDefaultStackSize(); + } + + static ThreadImpl::Id getId() + { + return ThreadImpl::getId(); + } + + static uint32_t getNbPhysicalCores() + { + return ThreadImpl::getNbPhysicalCores(); + } + + private: + class ThreadImpl* mImpl; +}; + +typedef ThreadT<> Thread; + +PX_FOUNDATION_API uint32_t TlsAlloc(); +PX_FOUNDATION_API void TlsFree(uint32_t index); +PX_FOUNDATION_API void* TlsGet(uint32_t index); +PX_FOUNDATION_API size_t TlsGetValue(uint32_t index); +PX_FOUNDATION_API uint32_t TlsSet(uint32_t index, void* value); +PX_FOUNDATION_API uint32_t TlsSetValue(uint32_t index, size_t value); + +} // namespace shdfnd +} // namespace physx + +#endif // #ifndef PSFOUNDATION_PSTHREAD_H diff --git a/sources/PhysX/PhysX/source/foundation/include/PsTime.h b/sources/PhysX/PhysX/source/foundation/include/PsTime.h new file mode 100644 index 00000000..677aa2eb --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsTime.h @@ -0,0 +1,96 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSTIME_H +#define PSFOUNDATION_PSTIME_H + +#include "Ps.h" +#include "foundation/PxFoundationConfig.h" + +#if PX_LINUX || PX_ANDROID +#include +#endif + +namespace physx +{ +namespace shdfnd +{ + +struct CounterFrequencyToTensOfNanos +{ + uint64_t mNumerator; + uint64_t mDenominator; + CounterFrequencyToTensOfNanos(uint64_t inNum, uint64_t inDenom) : mNumerator(inNum), mDenominator(inDenom) + { + } + + // quite slow. + uint64_t toTensOfNanos(uint64_t inCounter) const + { + return (inCounter * mNumerator) / mDenominator; + } +}; + +class PX_FOUNDATION_API Time +{ + public: + typedef double Second; + static const uint64_t sNumTensOfNanoSecondsInASecond = 100000000; + // This is supposedly guaranteed to not change after system boot + // regardless of processors, speedstep, etc. + static const CounterFrequencyToTensOfNanos& getBootCounterFrequency(); + + static CounterFrequencyToTensOfNanos getCounterFrequency(); + + static uint64_t getCurrentCounterValue(); + + // SLOW!! + // Thar be a 64 bit divide in thar! + static uint64_t getCurrentTimeInTensOfNanoSeconds() + { + uint64_t ticks = getCurrentCounterValue(); + return getBootCounterFrequency().toTensOfNanos(ticks); + } + + Time(); + Second getElapsedSeconds(); + Second peekElapsedSeconds(); + Second getLastTime() const; + + private: +#if PX_LINUX || PX_ANDROID || PX_APPLE_FAMILY || PX_PS4 + Second mLastTime; +#else + int64_t mTickCount; +#endif +}; +} // namespace shdfnd +} // namespace physx + +#endif // #ifndef PSFOUNDATION_PSTIME_H diff --git a/sources/PhysX/PhysX/source/foundation/include/PsUserAllocated.h b/sources/PhysX/PhysX/source/foundation/include/PsUserAllocated.h new file mode 100644 index 00000000..1f3d54ba --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsUserAllocated.h @@ -0,0 +1,104 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSUSERALLOCATED_H +#define PSFOUNDATION_PSUSERALLOCATED_H + +#include "PsAllocator.h" + +namespace physx +{ +namespace shdfnd +{ +/** +Provides new and delete using a UserAllocator. +Guarantees that 'delete x;' uses the UserAllocator too. +*/ +class UserAllocated +{ + public: + // PX_SERIALIZATION + PX_INLINE void* operator new(size_t, void* address) + { + return address; + } + //~PX_SERIALIZATION + // Matching operator delete to the above operator new. Don't ask me + // how this makes any sense - Nuernberger. + PX_INLINE void operator delete(void*, void*) + { + } + + template + PX_INLINE void* operator new(size_t size, Alloc alloc, const char* fileName, int line) + { + return alloc.allocate(size, fileName, line); + } + template + PX_INLINE void* operator new(size_t size, size_t /*align*/, Alloc alloc, const char* fileName, int line) + { + // align is not respected, we have 16bit aligned allocator + return alloc.allocate(size, fileName, line); + } + template + PX_INLINE void* operator new [](size_t size, Alloc alloc, const char* fileName, int line) + { return alloc.allocate(size, fileName, line); } + template + PX_INLINE void* operator new [](size_t size, size_t /*align*/, Alloc alloc, const char* fileName, int line) + { + // align is not respected, we have 16bit aligned allocator + return alloc.allocate(size, fileName, line); + } + + // placement delete + template + PX_INLINE void operator delete(void* ptr, Alloc alloc, const char* fileName, int line) + { + PX_UNUSED(fileName); + PX_UNUSED(line); + alloc.deallocate(ptr); + } + template + PX_INLINE void operator delete [](void* ptr, Alloc alloc, const char* fileName, int line) + { + PX_UNUSED(fileName); + PX_UNUSED(line); + alloc.deallocate(ptr); + } PX_INLINE void + operator delete(void* ptr) + { + NonTrackingAllocator().deallocate(ptr); + } + PX_INLINE void operator delete [](void* ptr) + { NonTrackingAllocator().deallocate(ptr); } +}; +} // namespace shdfnd +} // namespace physx + +#endif // #ifndef PSFOUNDATION_PSUSERALLOCATED_H diff --git a/sources/PhysX/PhysX/source/foundation/include/PsUtilities.h b/sources/PhysX/PhysX/source/foundation/include/PsUtilities.h new file mode 100644 index 00000000..ff57e058 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsUtilities.h @@ -0,0 +1,165 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSUTILITIES_H +#define PSFOUNDATION_PSUTILITIES_H + +#include "foundation/PxVec3.h" +#include "foundation/PxAssert.h" +#include "Ps.h" +#include "PsIntrinsics.h" +#include "PsBasicTemplates.h" + +namespace physx +{ +namespace shdfnd +{ +PX_INLINE char littleEndian() +{ + int i = 1; + return *(reinterpret_cast(&i)); +} + +// PT: checked casts +PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 to32(PxU64 value) +{ + PX_ASSERT(value <= 0xffffffff); + return PxU32(value); +} +PX_CUDA_CALLABLE PX_FORCE_INLINE PxU16 to16(PxU32 value) +{ + PX_ASSERT(value <= 0xffff); + return PxU16(value); +} +PX_CUDA_CALLABLE PX_FORCE_INLINE PxU8 to8(PxU16 value) +{ + PX_ASSERT(value <= 0xff); + return PxU8(value); +} +PX_CUDA_CALLABLE PX_FORCE_INLINE PxU8 to8(PxU32 value) +{ + PX_ASSERT(value <= 0xff); + return PxU8(value); +} +PX_CUDA_CALLABLE PX_FORCE_INLINE PxU8 to8(PxI32 value) +{ + PX_ASSERT(value <= 0xff); + PX_ASSERT(value >= 0); + return PxU8(value); +} +PX_CUDA_CALLABLE PX_FORCE_INLINE PxI8 toI8(PxU32 value) +{ + PX_ASSERT(value <= 0x7f); + return PxI8(value); +} + +/*! +Get number of elements in array +*/ +template +char (&ArraySizeHelper(T (&array)[N]))[N]; +#define PX_ARRAY_SIZE(_array) (sizeof(physx::shdfnd::ArraySizeHelper(_array))) + +/*! +Sort two elements using operator< + +On return x will be the smaller of the two +*/ +template +PX_CUDA_CALLABLE PX_FORCE_INLINE void order(T& x, T& y) +{ + if(y < x) + swap(x, y); +} + +// most architectures can do predication on real comparisons, and on VMX, it matters + +PX_CUDA_CALLABLE PX_FORCE_INLINE void order(PxReal& x, PxReal& y) +{ + PxReal newX = PxMin(x, y); + PxReal newY = PxMax(x, y); + x = newX; + y = newY; +} + +/*! +Sort two elements using operator< and also keep order +of any extra data +*/ +template +PX_CUDA_CALLABLE PX_FORCE_INLINE void order(T& x, T& y, E1& xe1, E1& ye1) +{ + if(y < x) + { + swap(x, y); + swap(xe1, ye1); + } +} + +#if PX_GCC_FAMILY && !PX_EMSCRIPTEN && !PX_LINUX +__attribute__((noreturn)) +#endif + PX_INLINE void debugBreak() +{ +#if PX_WINDOWS || PX_XBOXONE + __debugbreak(); +#elif PX_ANDROID + raise(SIGTRAP); // works better than __builtin_trap. Proper call stack and can be continued. +#elif PX_LINUX + asm("int $3"); +#elif PX_GCC_FAMILY + __builtin_trap(); +#else + PX_ASSERT(false); +#endif +} + +bool checkValid(const float&); +bool checkValid(const PxVec3&); +bool checkValid(const PxQuat&); +bool checkValid(const PxMat33&); +bool checkValid(const PxTransform&); +bool checkValid(const char*); + +// equivalent to std::max_element +template +inline const T* maxElement(const T* first, const T* last) +{ + const T* m = first; + for(const T* it = first + 1; it < last; ++it) + if(*m < *it) + m = it; + + return m; +} + +} // namespace shdfnd +} // namespace physx + +#endif diff --git a/sources/PhysX/PhysX/source/foundation/include/PsVecMath.h b/sources/PhysX/PhysX/source/foundation/include/PsVecMath.h new file mode 100644 index 00000000..fff56a97 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsVecMath.h @@ -0,0 +1,1344 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSVECMATH_H +#define PSFOUNDATION_PSVECMATH_H + +#include "Ps.h" +#include "PsIntrinsics.h" +#include "foundation/PxVec3.h" +#include "foundation/PxVec4.h" +#include "foundation/PxMat33.h" +#include "foundation/PxUnionCast.h" + +// We can opt to use the scalar version of vectorised functions. +// This can catch type safety issues and might even work out more optimal on pc. +// It will also be useful for benchmarking and testing. +// NEVER submit with vector intrinsics deactivated without good reason. +// AM: deactivating SIMD for debug win64 just so autobuild will also exercise +// non-SIMD path, until a dedicated non-SIMD platform sich as Arm comes online. +// TODO: dima: reference all platforms with SIMD support here, +// all unknown/experimental cases should better default to NO SIMD. + +// enable/disable SIMD +#if !defined(PX_SIMD_DISABLED) +#if PX_INTEL_FAMILY && (!defined(__EMSCRIPTEN__) || defined(__SSE2__)) +#define COMPILE_VECTOR_INTRINSICS 1 +#elif PX_ANDROID && PX_NEON +#define COMPILE_VECTOR_INTRINSICS 1 +#elif PX_UWP && PX_NEON +#define COMPILE_VECTOR_INTRINSICS 1 +#elif PX_IOS && PX_NEON +#define COMPILE_VECTOR_INTRINSICS 1 +#elif PX_SWITCH +#define COMPILE_VECTOR_INTRINSICS 1 +#else +#define COMPILE_VECTOR_INTRINSICS 0 +#endif +#else +#define COMPILE_VECTOR_INTRINSICS 0 +#endif + +#if COMPILE_VECTOR_INTRINSICS && PX_INTEL_FAMILY&&(PX_UNIX_FAMILY || PX_PS4) +// only SSE2 compatible platforms should reach this +#if PX_EMSCRIPTEN +#include +#endif +#include +#endif + +#if COMPILE_VECTOR_INTRINSICS +#include "PsAoS.h" +#else +#include "PsVecMathAoSScalar.h" +#endif + +namespace physx +{ +namespace shdfnd +{ +namespace aos +{ + +// Basic AoS types are +// FloatV - 16-byte aligned representation of float. +// Vec3V - 16-byte aligned representation of PxVec3 stored as (x y z 0). +// Vec4V - 16-byte aligned representation of vector of 4 floats stored as (x y z w). +// BoolV - 16-byte aligned representation of vector of 4 bools stored as (x y z w). +// VecU32V - 16-byte aligned representation of 4 unsigned ints stored as (x y z w). +// VecI32V - 16-byte aligned representation of 4 signed ints stored as (x y z w). +// Mat33V - 16-byte aligned representation of any 3x3 matrix. +// Mat34V - 16-byte aligned representation of transformation matrix (rotation in col1,col2,col3 and translation in +// col4). +// Mat44V - 16-byte aligned representation of any 4x4 matrix. + +////////////////////////////////////////// +// Construct a simd type from a scalar type +////////////////////////////////////////// + +// FloatV +//(f,f,f,f) +PX_FORCE_INLINE FloatV FLoad(const PxF32 f); + +// Vec3V +//(f,f,f,0) +PX_FORCE_INLINE Vec3V V3Load(const PxF32 f); +//(f.x,f.y,f.z,0) +PX_FORCE_INLINE Vec3V V3LoadU(const PxVec3& f); +//(f.x,f.y,f.z,0), f must be 16-byte aligned +PX_FORCE_INLINE Vec3V V3LoadA(const PxVec3& f); +//(f.x,f.y,f.z,w_undefined), f must be 16-byte aligned +PX_FORCE_INLINE Vec3V V3LoadUnsafeA(const PxVec3& f); +//(f.x,f.y,f.z,0) +PX_FORCE_INLINE Vec3V V3LoadU(const PxF32* f); +//(f.x,f.y,f.z,0), f must be 16-byte aligned +PX_FORCE_INLINE Vec3V V3LoadA(const PxF32* f); + +// Vec4V +//(f,f,f,f) +PX_FORCE_INLINE Vec4V V4Load(const PxF32 f); +//(f[0],f[1],f[2],f[3]) +PX_FORCE_INLINE Vec4V V4LoadU(const PxF32* const f); +//(f[0],f[1],f[2],f[3]), f must be 16-byte aligned +PX_FORCE_INLINE Vec4V V4LoadA(const PxF32* const f); +//(x,y,z,w) +PX_FORCE_INLINE Vec4V V4LoadXYZW(const PxF32& x, const PxF32& y, const PxF32& z, const PxF32& w); + +// BoolV +//(f,f,f,f) +PX_FORCE_INLINE BoolV BLoad(const bool f); +//(f[0],f[1],f[2],f[3]) +PX_FORCE_INLINE BoolV BLoad(const bool* const f); + +// VecU32V +//(f,f,f,f) +PX_FORCE_INLINE VecU32V U4Load(const PxU32 f); +//(f[0],f[1],f[2],f[3]) +PX_FORCE_INLINE VecU32V U4LoadU(const PxU32* f); +//(f[0],f[1],f[2],f[3]), f must be 16-byte aligned +PX_FORCE_INLINE VecU32V U4LoadA(const PxU32* f); +//((U32)x, (U32)y, (U32)z, (U32)w) +PX_FORCE_INLINE VecU32V U4LoadXYZW(PxU32 x, PxU32 y, PxU32 z, PxU32 w); + +// VecI32V +//(i,i,i,i) +PX_FORCE_INLINE VecI32V I4Load(const PxI32 i); +//(i,i,i,i) +PX_FORCE_INLINE VecI32V I4LoadU(const PxI32* i); +//(i,i,i,i) +PX_FORCE_INLINE VecI32V I4LoadA(const PxI32* i); + +// QuatV +//(x = v[0], y=v[1], z=v[2], w=v3[3]) and array don't need to aligned +PX_FORCE_INLINE QuatV QuatVLoadU(const PxF32* v); +//(x = v[0], y=v[1], z=v[2], w=v3[3]) and array need to aligned, fast load +PX_FORCE_INLINE QuatV QuatVLoadA(const PxF32* v); +//(x, y, z, w) +PX_FORCE_INLINE QuatV QuatVLoadXYZW(const PxF32 x, const PxF32 y, const PxF32 z, const PxF32 w); + +// not added to public api +Vec4V Vec4V_From_PxVec3_WUndefined(const PxVec3& v); + +/////////////////////////////////////////////////// +// Construct a simd type from a different simd type +/////////////////////////////////////////////////// + +// Vec3V +//(v.x,v.y,v.z,0) +PX_FORCE_INLINE Vec3V Vec3V_From_Vec4V(Vec4V v); +//(v.x,v.y,v.z,undefined) - be very careful with w!=0 because many functions require w==0 for correct operation eg V3Dot, V3Length, V3Cross etc etc. +PX_FORCE_INLINE Vec3V Vec3V_From_Vec4V_WUndefined(const Vec4V v); + +// Vec4V +//(f.x,f.y,f.z,f.w) +PX_FORCE_INLINE Vec4V Vec4V_From_Vec3V(Vec3V f); +//((PxF32)f.x, (PxF32)f.y, (PxF32)f.z, (PxF32)f.w) +PX_FORCE_INLINE Vec4V Vec4V_From_VecU32V(VecU32V a); +//((PxF32)f.x, (PxF32)f.y, (PxF32)f.z, (PxF32)f.w) +PX_FORCE_INLINE Vec4V Vec4V_From_VecI32V(VecI32V a); +//(*(reinterpret_cast(&f.x), (reinterpret_cast(&f.y), (reinterpret_cast(&f.z), +//(reinterpret_cast(&f.w)) +PX_FORCE_INLINE Vec4V Vec4V_ReinterpretFrom_VecU32V(VecU32V a); +//(*(reinterpret_cast(&f.x), (reinterpret_cast(&f.y), (reinterpret_cast(&f.z), +//(reinterpret_cast(&f.w)) +PX_FORCE_INLINE Vec4V Vec4V_ReinterpretFrom_VecI32V(VecI32V a); + +// VecU32V +//(*(reinterpret_cast(&f.x), (reinterpret_cast(&f.y), (reinterpret_cast(&f.z), +//(reinterpret_cast(&f.w)) +PX_FORCE_INLINE VecU32V VecU32V_ReinterpretFrom_Vec4V(Vec4V a); +//(b[0], b[1], b[2], b[3]) +PX_FORCE_INLINE VecU32V VecU32V_From_BoolV(const BoolVArg b); + +// VecI32V +//(*(reinterpret_cast(&f.x), (reinterpret_cast(&f.y), (reinterpret_cast(&f.z), +//(reinterpret_cast(&f.w)) +PX_FORCE_INLINE VecI32V VecI32V_ReinterpretFrom_Vec4V(Vec4V a); +//((I32)a.x, (I32)a.y, (I32)a.z, (I32)a.w) +PX_FORCE_INLINE VecI32V VecI32V_From_Vec4V(Vec4V a); +//((I32)b.x, (I32)b.y, (I32)b.z, (I32)b.w) +PX_FORCE_INLINE VecI32V VecI32V_From_BoolV(const BoolVArg b); + +/////////////////////////////////////////////////// +// Convert from a simd type back to a scalar type +/////////////////////////////////////////////////// + +// FloatV +// a.x +PX_FORCE_INLINE void FStore(const FloatV a, PxF32* PX_RESTRICT f); + +// Vec3V +//(a.x,a.y,a.z) +PX_FORCE_INLINE void V3StoreA(const Vec3V a, PxVec3& f); +//(a.x,a.y,a.z) +PX_FORCE_INLINE void V3StoreU(const Vec3V a, PxVec3& f); + +// Vec4V +PX_FORCE_INLINE void V4StoreA(const Vec4V a, PxF32* f); +PX_FORCE_INLINE void V4StoreU(const Vec4V a, PxF32* f); + +// BoolV +PX_FORCE_INLINE void BStoreA(const BoolV b, PxU32* f); + +// VecU32V +PX_FORCE_INLINE void U4StoreA(const VecU32V uv, PxU32* u); + +// VecI32V +PX_FORCE_INLINE void I4StoreA(const VecI32V iv, PxI32* i); + +////////////////////////////////////////////////////////////////// +// Test that simd types have elements in the floating point range +////////////////////////////////////////////////////////////////// + +// check for each component is valid ie in floating point range +PX_FORCE_INLINE bool isFiniteFloatV(const FloatV a); +// check for each component is valid ie in floating point range +PX_FORCE_INLINE bool isFiniteVec3V(const Vec3V a); +// check for each component is valid ie in floating point range +PX_FORCE_INLINE bool isFiniteVec4V(const Vec4V a); + +// Check that w-component is zero. +PX_FORCE_INLINE bool isValidVec3V(const Vec3V a); + +////////////////////////////////////////////////////////////////// +// Tests that all elements of two 16-byte types are completely equivalent. +// Use these tests for unit testing and asserts only. +////////////////////////////////////////////////////////////////// + +namespace _VecMathTests +{ +PX_FORCE_INLINE Vec3V getInvalidVec3V(); +PX_FORCE_INLINE bool allElementsEqualFloatV(const FloatV a, const FloatV b); +PX_FORCE_INLINE bool allElementsEqualVec3V(const Vec3V a, const Vec3V b); +PX_FORCE_INLINE bool allElementsEqualVec4V(const Vec4V a, const Vec4V b); +PX_FORCE_INLINE bool allElementsEqualBoolV(const BoolV a, const BoolV b); +PX_FORCE_INLINE bool allElementsEqualVecU32V(const VecU32V a, const VecU32V b); +PX_FORCE_INLINE bool allElementsEqualVecI32V(const VecI32V a, const VecI32V b); + +PX_FORCE_INLINE bool allElementsEqualMat33V(const Mat33V& a, const Mat33V& b) +{ + return (allElementsEqualVec3V(a.col0, b.col0) && allElementsEqualVec3V(a.col1, b.col1) && + allElementsEqualVec3V(a.col2, b.col2)); +} +PX_FORCE_INLINE bool allElementsEqualMat34V(const Mat34V& a, const Mat34V& b) +{ + return (allElementsEqualVec3V(a.col0, b.col0) && allElementsEqualVec3V(a.col1, b.col1) && + allElementsEqualVec3V(a.col2, b.col2) && allElementsEqualVec3V(a.col3, b.col3)); +} +PX_FORCE_INLINE bool allElementsEqualMat44V(const Mat44V& a, const Mat44V& b) +{ + return (allElementsEqualVec4V(a.col0, b.col0) && allElementsEqualVec4V(a.col1, b.col1) && + allElementsEqualVec4V(a.col2, b.col2) && allElementsEqualVec4V(a.col3, b.col3)); +} + +PX_FORCE_INLINE bool allElementsNearEqualFloatV(const FloatV a, const FloatV b); +PX_FORCE_INLINE bool allElementsNearEqualVec3V(const Vec3V a, const Vec3V b); +PX_FORCE_INLINE bool allElementsNearEqualVec4V(const Vec4V a, const Vec4V b); +PX_FORCE_INLINE bool allElementsNearEqualMat33V(const Mat33V& a, const Mat33V& b) +{ + return (allElementsNearEqualVec3V(a.col0, b.col0) && allElementsNearEqualVec3V(a.col1, b.col1) && + allElementsNearEqualVec3V(a.col2, b.col2)); +} +PX_FORCE_INLINE bool allElementsNearEqualMat34V(const Mat34V& a, const Mat34V& b) +{ + return (allElementsNearEqualVec3V(a.col0, b.col0) && allElementsNearEqualVec3V(a.col1, b.col1) && + allElementsNearEqualVec3V(a.col2, b.col2) && allElementsNearEqualVec3V(a.col3, b.col3)); +} +PX_FORCE_INLINE bool allElementsNearEqualMat44V(const Mat44V& a, const Mat44V& b) +{ + return (allElementsNearEqualVec4V(a.col0, b.col0) && allElementsNearEqualVec4V(a.col1, b.col1) && + allElementsNearEqualVec4V(a.col2, b.col2) && allElementsNearEqualVec4V(a.col3, b.col3)); +} +} + +////////////////////////////////////////////////////////////////// +// Math operations on FloatV +////////////////////////////////////////////////////////////////// + +//(0,0,0,0) +PX_FORCE_INLINE FloatV FZero(); +//(1,1,1,1) +PX_FORCE_INLINE FloatV FOne(); +//(0.5,0.5,0.5,0.5) +PX_FORCE_INLINE FloatV FHalf(); +//(PX_EPS_REAL,PX_EPS_REAL,PX_EPS_REAL,PX_EPS_REAL) +PX_FORCE_INLINE FloatV FEps(); +//(PX_MAX_REAL, PX_MAX_REAL, PX_MAX_REAL PX_MAX_REAL) +PX_FORCE_INLINE FloatV FMax(); +//(-PX_MAX_REAL, -PX_MAX_REAL, -PX_MAX_REAL -PX_MAX_REAL) +PX_FORCE_INLINE FloatV FNegMax(); +//(1e-6f, 1e-6f, 1e-6f, 1e-6f) +PX_FORCE_INLINE FloatV FEps6(); +//((PxF32*)&1, (PxF32*)&1, (PxF32*)&1, (PxF32*)&1) + +//-f (per component) +PX_FORCE_INLINE FloatV FNeg(const FloatV f); +// a+b (per component) +PX_FORCE_INLINE FloatV FAdd(const FloatV a, const FloatV b); +// a-b (per component) +PX_FORCE_INLINE FloatV FSub(const FloatV a, const FloatV b); +// a*b (per component) +PX_FORCE_INLINE FloatV FMul(const FloatV a, const FloatV b); +// a/b (per component) +PX_FORCE_INLINE FloatV FDiv(const FloatV a, const FloatV b); +// a/b (per component) +PX_FORCE_INLINE FloatV FDivFast(const FloatV a, const FloatV b); +// 1.0f/a +PX_FORCE_INLINE FloatV FRecip(const FloatV a); +// 1.0f/a +PX_FORCE_INLINE FloatV FRecipFast(const FloatV a); +// 1.0f/sqrt(a) +PX_FORCE_INLINE FloatV FRsqrt(const FloatV a); +// 1.0f/sqrt(a) +PX_FORCE_INLINE FloatV FRsqrtFast(const FloatV a); +// sqrt(a) +PX_FORCE_INLINE FloatV FSqrt(const FloatV a); +// a*b+c +PX_FORCE_INLINE FloatV FScaleAdd(const FloatV a, const FloatV b, const FloatV c); +// c-a*b +PX_FORCE_INLINE FloatV FNegScaleSub(const FloatV a, const FloatV b, const FloatV c); +// fabs(a) +PX_FORCE_INLINE FloatV FAbs(const FloatV a); +// c ? a : b (per component) +PX_FORCE_INLINE FloatV FSel(const BoolV c, const FloatV a, const FloatV b); +// a>b (per component) +PX_FORCE_INLINE BoolV FIsGrtr(const FloatV a, const FloatV b); +// a>=b (per component) +PX_FORCE_INLINE BoolV FIsGrtrOrEq(const FloatV a, const FloatV b); +// a==b (per component) +PX_FORCE_INLINE BoolV FIsEq(const FloatV a, const FloatV b); +// Max(a,b) (per component) +PX_FORCE_INLINE FloatV FMax(const FloatV a, const FloatV b); +// Min(a,b) (per component) +PX_FORCE_INLINE FloatV FMin(const FloatV a, const FloatV b); +// Clamp(a,b) (per component) +PX_FORCE_INLINE FloatV FClamp(const FloatV a, const FloatV minV, const FloatV maxV); + +// a.x>b.x +PX_FORCE_INLINE PxU32 FAllGrtr(const FloatV a, const FloatV b); +// a.x>=b.x +PX_FORCE_INLINE PxU32 FAllGrtrOrEq(const FloatV a, const FloatV b); +// a.x==b.x +PX_FORCE_INLINE PxU32 FAllEq(const FloatV a, const FloatV b); +// amax +PX_FORCE_INLINE PxU32 FOutOfBounds(const FloatV a, const FloatV min, const FloatV max); +// a>=min && a<=max +PX_FORCE_INLINE PxU32 FInBounds(const FloatV a, const FloatV min, const FloatV max); +// a<-bounds || a>bounds +PX_FORCE_INLINE PxU32 FOutOfBounds(const FloatV a, const FloatV bounds); +// a>=-bounds && a<=bounds +PX_FORCE_INLINE PxU32 FInBounds(const FloatV a, const FloatV bounds); + +// round float a to the near int +PX_FORCE_INLINE FloatV FRound(const FloatV a); +// calculate the sin of float a +PX_FORCE_INLINE FloatV FSin(const FloatV a); +// calculate the cos of float b +PX_FORCE_INLINE FloatV FCos(const FloatV a); + +////////////////////////////////////////////////////////////////// +// Math operations on Vec3V +////////////////////////////////////////////////////////////////// + +//(f,f,f,f) +PX_FORCE_INLINE Vec3V V3Splat(const FloatV f); + +//(x,y,z) +PX_FORCE_INLINE Vec3V V3Merge(const FloatVArg x, const FloatVArg y, const FloatVArg z); + +//(1,0,0,0) +PX_FORCE_INLINE Vec3V V3UnitX(); +//(0,1,0,0) +PX_FORCE_INLINE Vec3V V3UnitY(); +//(0,0,1,0) +PX_FORCE_INLINE Vec3V V3UnitZ(); + +//(f.x,f.x,f.x,f.x) +PX_FORCE_INLINE FloatV V3GetX(const Vec3V f); +//(f.y,f.y,f.y,f.y) +PX_FORCE_INLINE FloatV V3GetY(const Vec3V f); +//(f.z,f.z,f.z,f.z) +PX_FORCE_INLINE FloatV V3GetZ(const Vec3V f); + +//(f,v.y,v.z,v.w) +PX_FORCE_INLINE Vec3V V3SetX(const Vec3V v, const FloatV f); +//(v.x,f,v.z,v.w) +PX_FORCE_INLINE Vec3V V3SetY(const Vec3V v, const FloatV f); +//(v.x,v.y,f,v.w) +PX_FORCE_INLINE Vec3V V3SetZ(const Vec3V v, const FloatV f); + +// v.x=f +PX_FORCE_INLINE void V3WriteX(Vec3V& v, const PxF32 f); +// v.y=f +PX_FORCE_INLINE void V3WriteY(Vec3V& v, const PxF32 f); +// v.z=f +PX_FORCE_INLINE void V3WriteZ(Vec3V& v, const PxF32 f); +// v.x=f.x, v.y=f.y, v.z=f.z +PX_FORCE_INLINE void V3WriteXYZ(Vec3V& v, const PxVec3& f); +// return v.x +PX_FORCE_INLINE PxF32 V3ReadX(const Vec3V& v); +// return v.y +PX_FORCE_INLINE PxF32 V3ReadY(const Vec3V& v); +// return v.y +PX_FORCE_INLINE PxF32 V3ReadZ(const Vec3V& v); +// return (v.x,v.y,v.z) +PX_FORCE_INLINE const PxVec3& V3ReadXYZ(const Vec3V& v); + +//(a.x, b.x, c.x) +PX_FORCE_INLINE Vec3V V3ColX(const Vec3V a, const Vec3V b, const Vec3V c); +//(a.y, b.y, c.y) +PX_FORCE_INLINE Vec3V V3ColY(const Vec3V a, const Vec3V b, const Vec3V c); +//(a.z, b.z, c.z) +PX_FORCE_INLINE Vec3V V3ColZ(const Vec3V a, const Vec3V b, const Vec3V c); + +//(0,0,0,0) +PX_FORCE_INLINE Vec3V V3Zero(); +//(1,1,1,1) +PX_FORCE_INLINE Vec3V V3One(); +//(PX_EPS_REAL,PX_EPS_REAL,PX_EPS_REAL,PX_EPS_REAL) +PX_FORCE_INLINE Vec3V V3Eps(); +//-c (per component) +PX_FORCE_INLINE Vec3V V3Neg(const Vec3V c); +// a+b (per component) +PX_FORCE_INLINE Vec3V V3Add(const Vec3V a, const Vec3V b); +// a-b (per component) +PX_FORCE_INLINE Vec3V V3Sub(const Vec3V a, const Vec3V b); +// a*b (per component) +PX_FORCE_INLINE Vec3V V3Scale(const Vec3V a, const FloatV b); +// a*b (per component) +PX_FORCE_INLINE Vec3V V3Mul(const Vec3V a, const Vec3V b); +// a/b (per component) +PX_FORCE_INLINE Vec3V V3ScaleInv(const Vec3V a, const FloatV b); +// a/b (per component) +PX_FORCE_INLINE Vec3V V3Div(const Vec3V a, const Vec3V b); +// a/b (per component) +PX_FORCE_INLINE Vec3V V3ScaleInvFast(const Vec3V a, const FloatV b); +// a/b (per component) +PX_FORCE_INLINE Vec3V V3DivFast(const Vec3V a, const Vec3V b); +// 1.0f/a +PX_FORCE_INLINE Vec3V V3Recip(const Vec3V a); +// 1.0f/a +PX_FORCE_INLINE Vec3V V3RecipFast(const Vec3V a); +// 1.0f/sqrt(a) +PX_FORCE_INLINE Vec3V V3Rsqrt(const Vec3V a); +// 1.0f/sqrt(a) +PX_FORCE_INLINE Vec3V V3RsqrtFast(const Vec3V a); +// a*b+c +PX_FORCE_INLINE Vec3V V3ScaleAdd(const Vec3V a, const FloatV b, const Vec3V c); +// c-a*b +PX_FORCE_INLINE Vec3V V3NegScaleSub(const Vec3V a, const FloatV b, const Vec3V c); +// a*b+c +PX_FORCE_INLINE Vec3V V3MulAdd(const Vec3V a, const Vec3V b, const Vec3V c); +// c-a*b +PX_FORCE_INLINE Vec3V V3NegMulSub(const Vec3V a, const Vec3V b, const Vec3V c); +// fabs(a) +PX_FORCE_INLINE Vec3V V3Abs(const Vec3V a); + +// a.b +// Note: a.w and b.w must have value zero +PX_FORCE_INLINE FloatV V3Dot(const Vec3V a, const Vec3V b); +// aXb +// Note: a.w and b.w must have value zero +PX_FORCE_INLINE Vec3V V3Cross(const Vec3V a, const Vec3V b); +// |a.a|^1/2 +// Note: a.w must have value zero +PX_FORCE_INLINE FloatV V3Length(const Vec3V a); +// a.a +// Note: a.w must have value zero +PX_FORCE_INLINE FloatV V3LengthSq(const Vec3V a); +// a*|a.a|^-1/2 +// Note: a.w must have value zero +PX_FORCE_INLINE Vec3V V3Normalize(const Vec3V a); +// a.a>0 ? a*|a.a|^-1/2 : (0,0,0,0) +// Note: a.w must have value zero +PX_FORCE_INLINE FloatV V3Length(const Vec3V a); +// a.a>0 ? a*|a.a|^-1/2 : unsafeReturnValue +// Note: a.w must have value zero +PX_FORCE_INLINE Vec3V V3NormalizeSafe(const Vec3V a, const Vec3V unsafeReturnValue); +// a.x + a.y + a.z +// Note: a.w must have value zero +PX_FORCE_INLINE FloatV V3SumElems(const Vec3V a); + +// c ? a : b (per component) +PX_FORCE_INLINE Vec3V V3Sel(const BoolV c, const Vec3V a, const Vec3V b); +// a>b (per component) +PX_FORCE_INLINE BoolV V3IsGrtr(const Vec3V a, const Vec3V b); +// a>=b (per component) +PX_FORCE_INLINE BoolV V3IsGrtrOrEq(const Vec3V a, const Vec3V b); +// a==b (per component) +PX_FORCE_INLINE BoolV V3IsEq(const Vec3V a, const Vec3V b); +// Max(a,b) (per component) +PX_FORCE_INLINE Vec3V V3Max(const Vec3V a, const Vec3V b); +// Min(a,b) (per component) +PX_FORCE_INLINE Vec3V V3Min(const Vec3V a, const Vec3V b); + +// Extract the maximum value from a +// Note: a.w must have value zero +PX_FORCE_INLINE FloatV V3ExtractMax(const Vec3V a); + +// Extract the minimum value from a +// Note: a.w must have value zero +PX_FORCE_INLINE FloatV V3ExtractMin(const Vec3V a); + +// Clamp(a,b) (per component) +PX_FORCE_INLINE Vec3V V3Clamp(const Vec3V a, const Vec3V minV, const Vec3V maxV); + +// Extract the sign for each component +PX_FORCE_INLINE Vec3V V3Sign(const Vec3V a); + +// Test all components. +// (a.x>b.x && a.y>b.y && a.z>b.z) +// Note: a.w and b.w must have value zero +PX_FORCE_INLINE PxU32 V3AllGrtr(const Vec3V a, const Vec3V b); +// (a.x>=b.x && a.y>=b.y && a.z>=b.z) +// Note: a.w and b.w must have value zero +PX_FORCE_INLINE PxU32 V3AllGrtrOrEq(const Vec3V a, const Vec3V b); +// (a.x==b.x && a.y==b.y && a.z==b.z) +// Note: a.w and b.w must have value zero +PX_FORCE_INLINE PxU32 V3AllEq(const Vec3V a, const Vec3V b); +// a.xmax.x || a.y>max.y || a.z>max.z +// Note: a.w and min.w and max.w must have value zero +PX_FORCE_INLINE PxU32 V3OutOfBounds(const Vec3V a, const Vec3V min, const Vec3V max); +// a.x>=min.x && a.y>=min.y && a.z>=min.z && a.x<=max.x && a.y<=max.y && a.z<=max.z +// Note: a.w and min.w and max.w must have value zero +PX_FORCE_INLINE PxU32 V3InBounds(const Vec3V a, const Vec3V min, const Vec3V max); +// a.x<-bounds.x || a.y<=-bounds.y || a.zbounds.x || a.y>bounds.y || a.z>bounds.z +// Note: a.w and bounds.w must have value zero +PX_FORCE_INLINE PxU32 V3OutOfBounds(const Vec3V a, const Vec3V bounds); +// a.x>=-bounds.x && a.y>=-bounds.y && a.z>=-bounds.z && a.x<=bounds.x && a.y<=bounds.y && a.z<=bounds.z +// Note: a.w and bounds.w must have value zero +PX_FORCE_INLINE PxU32 V3InBounds(const Vec3V a, const Vec3V bounds); + +//(floor(a.x + 0.5f), floor(a.y + 0.5f), floor(a.z + 0.5f)) +PX_FORCE_INLINE Vec3V V3Round(const Vec3V a); + +//(sinf(a.x), sinf(a.y), sinf(a.z)) +PX_FORCE_INLINE Vec3V V3Sin(const Vec3V a); +//(cosf(a.x), cosf(a.y), cosf(a.z)) +PX_FORCE_INLINE Vec3V V3Cos(const Vec3V a); + +//(a.y,a.z,a.z) +PX_FORCE_INLINE Vec3V V3PermYZZ(const Vec3V a); +//(a.x,a.y,a.x) +PX_FORCE_INLINE Vec3V V3PermXYX(const Vec3V a); +//(a.y,a.z,a.x) +PX_FORCE_INLINE Vec3V V3PermYZX(const Vec3V a); +//(a.z, a.x, a.y) +PX_FORCE_INLINE Vec3V V3PermZXY(const Vec3V a); +//(a.z,a.z,a.y) +PX_FORCE_INLINE Vec3V V3PermZZY(const Vec3V a); +//(a.y,a.x,a.x) +PX_FORCE_INLINE Vec3V V3PermYXX(const Vec3V a); +//(0, v1.z, v0.y) +PX_FORCE_INLINE Vec3V V3Perm_Zero_1Z_0Y(const Vec3V v0, const Vec3V v1); +//(v0.z, 0, v1.x) +PX_FORCE_INLINE Vec3V V3Perm_0Z_Zero_1X(const Vec3V v0, const Vec3V v1); +//(v1.y, v0.x, 0) +PX_FORCE_INLINE Vec3V V3Perm_1Y_0X_Zero(const Vec3V v0, const Vec3V v1); + +// Transpose 3 Vec3Vs inplace. Sets the w component to zero +// [ x0, y0, z0, w0] [ x1, y1, z1, w1] [ x2, y2, z2, w2] -> [x0 x1 x2 0] [y0 y1 y2 0] [z0 z1 z2 0] +PX_FORCE_INLINE void V3Transpose(Vec3V& col0, Vec3V& col1, Vec3V& col2); + +////////////////////////////////////////////////////////////////// +// Math operations on Vec4V +////////////////////////////////////////////////////////////////// + +//(f,f,f,f) +PX_FORCE_INLINE Vec4V V4Splat(const FloatV f); + +//(f[0],f[1],f[2],f[3]) +PX_FORCE_INLINE Vec4V V4Merge(const FloatV* const f); +//(x,y,z,w) +PX_FORCE_INLINE Vec4V V4Merge(const FloatVArg x, const FloatVArg y, const FloatVArg z, const FloatVArg w); +//(x.w, y.w, z.w, w.w) +PX_FORCE_INLINE Vec4V V4MergeW(const Vec4VArg x, const Vec4VArg y, const Vec4VArg z, const Vec4VArg w); +//(x.z, y.z, z.z, w.z) +PX_FORCE_INLINE Vec4V V4MergeZ(const Vec4VArg x, const Vec4VArg y, const Vec4VArg z, const Vec4VArg w); +//(x.y, y.y, z.y, w.y) +PX_FORCE_INLINE Vec4V V4MergeY(const Vec4VArg x, const Vec4VArg y, const Vec4VArg z, const Vec4VArg w); +//(x.x, y.x, z.x, w.x) +PX_FORCE_INLINE Vec4V V4MergeX(const Vec4VArg x, const Vec4VArg y, const Vec4VArg z, const Vec4VArg w); + +//(a.x, b.x, a.y, b.y) +PX_FORCE_INLINE Vec4V V4UnpackXY(const Vec4VArg a, const Vec4VArg b); +//(a.z, b.z, a.w, b.w) +PX_FORCE_INLINE Vec4V V4UnpackZW(const Vec4VArg a, const Vec4VArg b); + +//(1,0,0,0) +PX_FORCE_INLINE Vec4V V4UnitW(); +//(0,1,0,0) +PX_FORCE_INLINE Vec4V V4UnitY(); +//(0,0,1,0) +PX_FORCE_INLINE Vec4V V4UnitZ(); +//(0,0,0,1) +PX_FORCE_INLINE Vec4V V4UnitW(); + +//(f.x,f.x,f.x,f.x) +PX_FORCE_INLINE FloatV V4GetX(const Vec4V f); +//(f.y,f.y,f.y,f.y) +PX_FORCE_INLINE FloatV V4GetY(const Vec4V f); +//(f.z,f.z,f.z,f.z) +PX_FORCE_INLINE FloatV V4GetZ(const Vec4V f); +//(f.w,f.w,f.w,f.w) +PX_FORCE_INLINE FloatV V4GetW(const Vec4V f); + +//(f,v.y,v.z,v.w) +PX_FORCE_INLINE Vec4V V4SetX(const Vec4V v, const FloatV f); +//(v.x,f,v.z,v.w) +PX_FORCE_INLINE Vec4V V4SetY(const Vec4V v, const FloatV f); +//(v.x,v.y,f,v.w) +PX_FORCE_INLINE Vec4V V4SetZ(const Vec4V v, const FloatV f); +//(v.x,v.y,v.z,f) +PX_FORCE_INLINE Vec4V V4SetW(const Vec4V v, const FloatV f); + +//(v.x,v.y,v.z,0) +PX_FORCE_INLINE Vec4V V4ClearW(const Vec4V v); + +//(a[elementIndex], a[elementIndex], a[elementIndex], a[elementIndex]) +template +PX_FORCE_INLINE Vec4V V4SplatElement(Vec4V a); + +// v.x=f +PX_FORCE_INLINE void V4WriteX(Vec4V& v, const PxF32 f); +// v.y=f +PX_FORCE_INLINE void V4WriteY(Vec4V& v, const PxF32 f); +// v.z=f +PX_FORCE_INLINE void V4WriteZ(Vec4V& v, const PxF32 f); +// v.w=f +PX_FORCE_INLINE void V4WriteW(Vec4V& v, const PxF32 f); +// v.x=f.x, v.y=f.y, v.z=f.z +PX_FORCE_INLINE void V4WriteXYZ(Vec4V& v, const PxVec3& f); +// return v.x +PX_FORCE_INLINE PxF32 V4ReadX(const Vec4V& v); +// return v.y +PX_FORCE_INLINE PxF32 V4ReadY(const Vec4V& v); +// return v.z +PX_FORCE_INLINE PxF32 V4ReadZ(const Vec4V& v); +// return v.w +PX_FORCE_INLINE PxF32 V4ReadW(const Vec4V& v); +// return (v.x,v.y,v.z) +PX_FORCE_INLINE const PxVec3& V4ReadXYZ(const Vec4V& v); + +//(0,0,0,0) +PX_FORCE_INLINE Vec4V V4Zero(); +//(1,1,1,1) +PX_FORCE_INLINE Vec4V V4One(); +//(PX_EPS_REAL,PX_EPS_REAL,PX_EPS_REAL,PX_EPS_REAL) +PX_FORCE_INLINE Vec4V V4Eps(); + +//-c (per component) +PX_FORCE_INLINE Vec4V V4Neg(const Vec4V c); +// a+b (per component) +PX_FORCE_INLINE Vec4V V4Add(const Vec4V a, const Vec4V b); +// a-b (per component) +PX_FORCE_INLINE Vec4V V4Sub(const Vec4V a, const Vec4V b); +// a*b (per component) +PX_FORCE_INLINE Vec4V V4Scale(const Vec4V a, const FloatV b); +// a*b (per component) +PX_FORCE_INLINE Vec4V V4Mul(const Vec4V a, const Vec4V b); +// a/b (per component) +PX_FORCE_INLINE Vec4V V4ScaleInv(const Vec4V a, const FloatV b); +// a/b (per component) +PX_FORCE_INLINE Vec4V V4Div(const Vec4V a, const Vec4V b); +// a/b (per component) +PX_FORCE_INLINE Vec4V V4ScaleInvFast(const Vec4V a, const FloatV b); +// a/b (per component) +PX_FORCE_INLINE Vec4V V4DivFast(const Vec4V a, const Vec4V b); +// 1.0f/a +PX_FORCE_INLINE Vec4V V4Recip(const Vec4V a); +// 1.0f/a +PX_FORCE_INLINE Vec4V V4RecipFast(const Vec4V a); +// 1.0f/sqrt(a) +PX_FORCE_INLINE Vec4V V4Rsqrt(const Vec4V a); +// 1.0f/sqrt(a) +PX_FORCE_INLINE Vec4V V4RsqrtFast(const Vec4V a); +// a*b+c +PX_FORCE_INLINE Vec4V V4ScaleAdd(const Vec4V a, const FloatV b, const Vec4V c); +// c-a*b +PX_FORCE_INLINE Vec4V V4NegScaleSub(const Vec4V a, const FloatV b, const Vec4V c); +// a*b+c +PX_FORCE_INLINE Vec4V V4MulAdd(const Vec4V a, const Vec4V b, const Vec4V c); +// c-a*b +PX_FORCE_INLINE Vec4V V4NegMulSub(const Vec4V a, const Vec4V b, const Vec4V c); + +// fabs(a) +PX_FORCE_INLINE Vec4V V4Abs(const Vec4V a); +// bitwise a & ~b +PX_FORCE_INLINE Vec4V V4Andc(const Vec4V a, const VecU32V b); + +// a.b (W is taken into account) +PX_FORCE_INLINE FloatV V4Dot(const Vec4V a, const Vec4V b); +// a.b (same computation as V3Dot. W is ignored in input) +PX_FORCE_INLINE FloatV V4Dot3(const Vec4V a, const Vec4V b); +// aXb (same computation as V3Cross. W is ignored in input and undefined in output) +PX_FORCE_INLINE Vec4V V4Cross(const Vec4V a, const Vec4V b); + +//|a.a|^1/2 +PX_FORCE_INLINE FloatV V4Length(const Vec4V a); +// a.a +PX_FORCE_INLINE FloatV V4LengthSq(const Vec4V a); + +// a*|a.a|^-1/2 +PX_FORCE_INLINE Vec4V V4Normalize(const Vec4V a); +// a.a>0 ? a*|a.a|^-1/2 : unsafeReturnValue +PX_FORCE_INLINE Vec4V V4NormalizeSafe(const Vec4V a, const Vec4V unsafeReturnValue); +// a*|a.a|^-1/2 +PX_FORCE_INLINE Vec4V V4NormalizeFast(const Vec4V a); + +// c ? a : b (per component) +PX_FORCE_INLINE Vec4V V4Sel(const BoolV c, const Vec4V a, const Vec4V b); +// a>b (per component) +PX_FORCE_INLINE BoolV V4IsGrtr(const Vec4V a, const Vec4V b); +// a>=b (per component) +PX_FORCE_INLINE BoolV V4IsGrtrOrEq(const Vec4V a, const Vec4V b); +// a==b (per component) +PX_FORCE_INLINE BoolV V4IsEq(const Vec4V a, const Vec4V b); +// Max(a,b) (per component) +PX_FORCE_INLINE Vec4V V4Max(const Vec4V a, const Vec4V b); +// Min(a,b) (per component) +PX_FORCE_INLINE Vec4V V4Min(const Vec4V a, const Vec4V b); +// Get the maximum component from a +PX_FORCE_INLINE FloatV V4ExtractMax(const Vec4V a); +// Get the minimum component from a +PX_FORCE_INLINE FloatV V4ExtractMin(const Vec4V a); + +// Clamp(a,b) (per component) +PX_FORCE_INLINE Vec4V V4Clamp(const Vec4V a, const Vec4V minV, const Vec4V maxV); + +// return 1 if all components of a are greater than all components of b. +PX_FORCE_INLINE PxU32 V4AllGrtr(const Vec4V a, const Vec4V b); +// return 1 if all components of a are greater than or equal to all components of b +PX_FORCE_INLINE PxU32 V4AllGrtrOrEq(const Vec4V a, const Vec4V b); +// return 1 if XYZ components of a are greater than or equal to XYZ components of b. W is ignored. +PX_FORCE_INLINE PxU32 V4AllGrtrOrEq3(const Vec4V a, const Vec4V b); +// return 1 if all components of a are equal to all components of b +PX_FORCE_INLINE PxU32 V4AllEq(const Vec4V a, const Vec4V b); +// return 1 if any XYZ component of a is greater than the corresponding component of b. W is ignored. +PX_FORCE_INLINE PxU32 V4AnyGrtr3(const Vec4V a, const Vec4V b); + +// round(a)(per component) +PX_FORCE_INLINE Vec4V V4Round(const Vec4V a); +// sin(a) (per component) +PX_FORCE_INLINE Vec4V V4Sin(const Vec4V a); +// cos(a) (per component) +PX_FORCE_INLINE Vec4V V4Cos(const Vec4V a); + +// Permute v into a new vec4v with YXWZ format +PX_FORCE_INLINE Vec4V V4PermYXWZ(const Vec4V v); +// Permute v into a new vec4v with XZXZ format +PX_FORCE_INLINE Vec4V V4PermXZXZ(const Vec4V v); +// Permute v into a new vec4v with YWYW format +PX_FORCE_INLINE Vec4V V4PermYWYW(const Vec4V v); +// Permute v into a new vec4v with YZXW format +PX_FORCE_INLINE Vec4V V4PermYZXW(const Vec4V v); +// Permute v into a new vec4v with ZWXY format - equivalent to a swap of the two 64bit parts of the vector +PX_FORCE_INLINE Vec4V V4PermZWXY(const Vec4V a); + +// Permute v into a new vec4v with format {a[x], a[y], a[z], a[w]} +// V4Perm<1,3,1,3> is equal to V4PermYWYW +// V4Perm<0,2,0,2> is equal to V4PermXZXZ +// V3Perm<1,0,3,2> is equal to V4PermYXWZ +template +PX_FORCE_INLINE Vec4V V4Perm(const Vec4V a); + +// Transpose 4 Vec4Vs inplace. +// [ x0, y0, z0, w0] [ x1, y1, z1, w1] [ x2, y2, z2, w2] [ x3, y3, z3, w3] -> +// [ x0, x1, x2, x3] [ y0, y1, y2, y3] [ z0, z1, z2, z3] [ w0, w1, w2, w3] +PX_FORCE_INLINE void V3Transpose(Vec3V& col0, Vec3V& col1, Vec3V& col2); + +// q = cos(a/2) + u*sin(a/2) +PX_FORCE_INLINE QuatV QuatV_From_RotationAxisAngle(const Vec3V u, const FloatV a); +// convert q to a unit quaternion +PX_FORCE_INLINE QuatV QuatNormalize(const QuatV q); +//|q.q|^1/2 +PX_FORCE_INLINE FloatV QuatLength(const QuatV q); +// q.q +PX_FORCE_INLINE FloatV QuatLengthSq(const QuatV q); +// a.b +PX_FORCE_INLINE FloatV QuatDot(const QuatV a, const QuatV b); +//(-q.x, -q.y, -q.z, q.w) +PX_FORCE_INLINE QuatV QuatConjugate(const QuatV q); +//(q.x, q.y, q.z) +PX_FORCE_INLINE Vec3V QuatGetImaginaryPart(const QuatV q); +// convert quaternion to matrix 33 +PX_FORCE_INLINE Mat33V QuatGetMat33V(const QuatVArg q); +// convert quaternion to matrix 33 +PX_FORCE_INLINE void QuatGetMat33V(const QuatVArg q, Vec3V& column0, Vec3V& column1, Vec3V& column2); +// convert matrix 33 to quaternion +PX_FORCE_INLINE QuatV Mat33GetQuatV(const Mat33V& a); +// brief computes rotation of x-axis +PX_FORCE_INLINE Vec3V QuatGetBasisVector0(const QuatV q); +// brief computes rotation of y-axis +PX_FORCE_INLINE Vec3V QuatGetBasisVector1(const QuatV q); +// brief computes rotation of z-axis +PX_FORCE_INLINE Vec3V QuatGetBasisVector2(const QuatV q); +// calculate the rotation vector from q and v +PX_FORCE_INLINE Vec3V QuatRotate(const QuatV q, const Vec3V v); +// calculate the rotation vector from the conjugate quaternion and v +PX_FORCE_INLINE Vec3V QuatRotateInv(const QuatV q, const Vec3V v); +// quaternion multiplication +PX_FORCE_INLINE QuatV QuatMul(const QuatV a, const QuatV b); +// quaternion add +PX_FORCE_INLINE QuatV QuatAdd(const QuatV a, const QuatV b); +// (-q.x, -q.y, -q.z, -q.w) +PX_FORCE_INLINE QuatV QuatNeg(const QuatV q); +// (a.x - b.x, a.y-b.y, a.z-b.z, a.w-b.w ) +PX_FORCE_INLINE QuatV QuatSub(const QuatV a, const QuatV b); +// (a.x*b, a.y*b, a.z*b, a.w*b) +PX_FORCE_INLINE QuatV QuatScale(const QuatV a, const FloatV b); +// (x = v[0], y = v[1], z = v[2], w =v[3]) +PX_FORCE_INLINE QuatV QuatMerge(const FloatV* const v); +// (x = v[0], y = v[1], z = v[2], w =v[3]) +PX_FORCE_INLINE QuatV QuatMerge(const FloatVArg x, const FloatVArg y, const FloatVArg z, const FloatVArg w); +// (x = 0.f, y = 0.f, z = 0.f, w = 1.f) +PX_FORCE_INLINE QuatV QuatIdentity(); +// check for each component is valid +PX_FORCE_INLINE bool isFiniteQuatV(const QuatV q); +// check for each component is valid +PX_FORCE_INLINE bool isValidQuatV(const QuatV q); +// check for each component is valid +PX_FORCE_INLINE bool isSaneQuatV(const QuatV q); + +// Math operations on 16-byte aligned booleans. +// x=false y=false z=false w=false +PX_FORCE_INLINE BoolV BFFFF(); +// x=false y=false z=false w=true +PX_FORCE_INLINE BoolV BFFFT(); +// x=false y=false z=true w=false +PX_FORCE_INLINE BoolV BFFTF(); +// x=false y=false z=true w=true +PX_FORCE_INLINE BoolV BFFTT(); +// x=false y=true z=false w=false +PX_FORCE_INLINE BoolV BFTFF(); +// x=false y=true z=false w=true +PX_FORCE_INLINE BoolV BFTFT(); +// x=false y=true z=true w=false +PX_FORCE_INLINE BoolV BFTTF(); +// x=false y=true z=true w=true +PX_FORCE_INLINE BoolV BFTTT(); +// x=true y=false z=false w=false +PX_FORCE_INLINE BoolV BTFFF(); +// x=true y=false z=false w=true +PX_FORCE_INLINE BoolV BTFFT(); +// x=true y=false z=true w=false +PX_FORCE_INLINE BoolV BTFTF(); +// x=true y=false z=true w=true +PX_FORCE_INLINE BoolV BTFTT(); +// x=true y=true z=false w=false +PX_FORCE_INLINE BoolV BTTFF(); +// x=true y=true z=false w=true +PX_FORCE_INLINE BoolV BTTFT(); +// x=true y=true z=true w=false +PX_FORCE_INLINE BoolV BTTTF(); +// x=true y=true z=true w=true +PX_FORCE_INLINE BoolV BTTTT(); + +// x=false y=false z=false w=true +PX_FORCE_INLINE BoolV BWMask(); +// x=true y=false z=false w=false +PX_FORCE_INLINE BoolV BXMask(); +// x=false y=true z=false w=false +PX_FORCE_INLINE BoolV BYMask(); +// x=false y=false z=true w=false +PX_FORCE_INLINE BoolV BZMask(); + +// get x component +PX_FORCE_INLINE BoolV BGetX(const BoolV f); +// get y component +PX_FORCE_INLINE BoolV BGetY(const BoolV f); +// get z component +PX_FORCE_INLINE BoolV BGetZ(const BoolV f); +// get w component +PX_FORCE_INLINE BoolV BGetW(const BoolV f); + +// Use elementIndex to splat xxxx or yyyy or zzzz or wwww +template +PX_FORCE_INLINE BoolV BSplatElement(Vec4V a); + +// component-wise && (AND) +PX_FORCE_INLINE BoolV BAnd(const BoolV a, const BoolV b); +// component-wise || (OR) +PX_FORCE_INLINE BoolV BOr(const BoolV a, const BoolV b); +// component-wise not +PX_FORCE_INLINE BoolV BNot(const BoolV a); + +// if all four components are true, return true, otherwise return false +PX_FORCE_INLINE BoolV BAllTrue4(const BoolV a); + +// if any four components is true, return true, otherwise return false +PX_FORCE_INLINE BoolV BAnyTrue4(const BoolV a); + +// if all three(0, 1, 2) components are true, return true, otherwise return false +PX_FORCE_INLINE BoolV BAllTrue3(const BoolV a); + +// if any three (0, 1, 2) components is true, return true, otherwise return false +PX_FORCE_INLINE BoolV BAnyTrue3(const BoolV a); + +// Return 1 if all components equal, zero otherwise. +PX_FORCE_INLINE PxU32 BAllEq(const BoolV a, const BoolV b); + +// Specialized/faster BAllEq function for b==TTTT +PX_FORCE_INLINE PxU32 BAllEqTTTT(const BoolV a); +// Specialized/faster BAllEq function for b==FFFF +PX_FORCE_INLINE PxU32 BAllEqFFFF(const BoolV a); + +/// Get BoolV as bits set in an PxU32. A bit in the output is set if the element is 'true' in the input. +/// There is a bit for each element in a, with element 0s value held in bit0, element 1 in bit 1s and so forth. +/// If nothing is true in the input it will return 0, and if all are true if will return 0xf. +/// NOTE! That performance of the function varies considerably by platform, thus it is recommended to use +/// where your algorithm really needs a BoolV in an integer variable. +PX_FORCE_INLINE PxU32 BGetBitMask(const BoolV a); + +// VecI32V stuff + +PX_FORCE_INLINE VecI32V VecI32V_Zero(); + +PX_FORCE_INLINE VecI32V VecI32V_One(); + +PX_FORCE_INLINE VecI32V VecI32V_Two(); + +PX_FORCE_INLINE VecI32V VecI32V_MinusOne(); + +// Compute a shift parameter for VecI32V_LeftShift and VecI32V_RightShift +// Each element of shift must be identical ie the vector must have form {count, count, count, count} with count>=0 +PX_FORCE_INLINE VecShiftV VecI32V_PrepareShift(const VecI32VArg shift); + +// Shift each element of a leftwards by the same amount +// Compute shift with VecI32V_PrepareShift +//{a.x<>shift[0], a.y>>shift[0], a.z>>shift[0], a.w>>shift[0]} +PX_FORCE_INLINE VecI32V VecI32V_RightShift(const VecI32VArg a, const VecShiftVArg shift); + +PX_FORCE_INLINE VecI32V VecI32V_Add(const VecI32VArg a, const VecI32VArg b); + +PX_FORCE_INLINE VecI32V VecI32V_Or(const VecI32VArg a, const VecI32VArg b); + +PX_FORCE_INLINE VecI32V VecI32V_GetX(const VecI32VArg a); + +PX_FORCE_INLINE VecI32V VecI32V_GetY(const VecI32VArg a); + +PX_FORCE_INLINE VecI32V VecI32V_GetZ(const VecI32VArg a); + +PX_FORCE_INLINE VecI32V VecI32V_GetW(const VecI32VArg a); + +PX_FORCE_INLINE VecI32V VecI32V_Sub(const VecI32VArg a, const VecI32VArg b); + +PX_FORCE_INLINE BoolV VecI32V_IsGrtr(const VecI32VArg a, const VecI32VArg b); + +PX_FORCE_INLINE BoolV VecI32V_IsEq(const VecI32VArg a, const VecI32VArg b); + +PX_FORCE_INLINE VecI32V V4I32Sel(const BoolV c, const VecI32V a, const VecI32V b); + +// VecU32V stuff + +PX_FORCE_INLINE VecU32V U4Zero(); + +PX_FORCE_INLINE VecU32V U4One(); + +PX_FORCE_INLINE VecU32V U4Two(); + +PX_FORCE_INLINE BoolV V4IsEqU32(const VecU32V a, const VecU32V b); + +PX_FORCE_INLINE VecU32V V4U32Sel(const BoolV c, const VecU32V a, const VecU32V b); + +PX_FORCE_INLINE VecU32V V4U32or(VecU32V a, VecU32V b); + +PX_FORCE_INLINE VecU32V V4U32xor(VecU32V a, VecU32V b); + +PX_FORCE_INLINE VecU32V V4U32and(VecU32V a, VecU32V b); + +PX_FORCE_INLINE VecU32V V4U32Andc(VecU32V a, VecU32V b); + +// VecU32 - why does this not return a bool? +PX_FORCE_INLINE VecU32V V4IsGrtrV32u(const Vec4V a, const Vec4V b); + +// Math operations on 16-byte aligned Mat33s (represents any 3x3 matrix) +PX_FORCE_INLINE Mat33V M33Load(const PxMat33& m) +{ + return Mat33V(Vec3V_From_Vec4V(V4LoadU(&m.column0.x)), + Vec3V_From_Vec4V(V4LoadU(&m.column1.x)), V3LoadU(m.column2)); +} +// a*b +PX_FORCE_INLINE Vec3V M33MulV3(const Mat33V& a, const Vec3V b); +// A*x + b +PX_FORCE_INLINE Vec3V M33MulV3AddV3(const Mat33V& A, const Vec3V b, const Vec3V c); +// transpose(a) * b +PX_FORCE_INLINE Vec3V M33TrnspsMulV3(const Mat33V& a, const Vec3V b); +// a*b +PX_FORCE_INLINE Mat33V M33MulM33(const Mat33V& a, const Mat33V& b); +// a+b +PX_FORCE_INLINE Mat33V M33Add(const Mat33V& a, const Mat33V& b); +// a+b +PX_FORCE_INLINE Mat33V M33Sub(const Mat33V& a, const Mat33V& b); +//-a +PX_FORCE_INLINE Mat33V M33Neg(const Mat33V& a); +// absolute value of the matrix +PX_FORCE_INLINE Mat33V M33Abs(const Mat33V& a); +// inverse mat +PX_FORCE_INLINE Mat33V M33Inverse(const Mat33V& a); +// transpose(a) +PX_FORCE_INLINE Mat33V M33Trnsps(const Mat33V& a); +// create an identity matrix +PX_FORCE_INLINE Mat33V M33Identity(); + +// create a vec3 to store the diagonal element of the M33 +PX_FORCE_INLINE Mat33V M33Diagonal(const Vec3VArg); + +// Not implemented +// return 1 if all components of a are equal to all components of b +// PX_FORCE_INLINE PxU32 V4U32AllEq(const VecU32V a, const VecU32V b); +// v.w=f +// PX_FORCE_INLINE void V3WriteW(Vec3V& v, const PxF32 f); +// PX_FORCE_INLINE PxF32 V3ReadW(const Vec3V& v); + +// Not used +// PX_FORCE_INLINE Vec4V V4LoadAligned(Vec4V* addr); +// PX_FORCE_INLINE Vec4V V4LoadUnaligned(Vec4V* addr); +// floor(a)(per component) +// PX_FORCE_INLINE Vec4V V4Floor(Vec4V a); +// ceil(a) (per component) +// PX_FORCE_INLINE Vec4V V4Ceil(Vec4V a); +// PX_FORCE_INLINE VecU32V V4ConvertToU32VSaturate(const Vec4V a, PxU32 power); + +// Math operations on 16-byte aligned Mat34s (represents transformation matrix - rotation and translation). +// namespace _Mat34V +//{ +// //a*b +// PX_FORCE_INLINE Vec3V multiplyV(const Mat34V& a, const Vec3V b); +// //a_rotation * b +// PX_FORCE_INLINE Vec3V multiply3X3V(const Mat34V& a, const Vec3V b); +// //transpose(a_rotation)*b +// PX_FORCE_INLINE Vec3V multiplyTranspose3X3V(const Mat34V& a, const Vec3V b); +// //a*b +// PX_FORCE_INLINE Mat34V multiplyV(const Mat34V& a, const Mat34V& b); +// //a_rotation*b +// PX_FORCE_INLINE Mat33V multiply3X3V(const Mat34V& a, const Mat33V& b); +// //a_rotation*b_rotation +// PX_FORCE_INLINE Mat33V multiply3X3V(const Mat34V& a, const Mat34V& b); +// //a+b +// PX_FORCE_INLINE Mat34V addV(const Mat34V& a, const Mat34V& b); +// //a^-1 +// PX_FORCE_INLINE Mat34V getInverseV(const Mat34V& a); +// //transpose(a_rotation) +// PX_FORCE_INLINE Mat33V getTranspose3X3(const Mat34V& a); +//}; //namespace _Mat34V + +// a*b +//#define M34MulV3(a,b) (M34MulV3(a,b)) +////a_rotation * b +//#define M34Mul33V3(a,b) (M34Mul33V3(a,b)) +////transpose(a_rotation)*b +//#define M34TrnspsMul33V3(a,b) (M34TrnspsMul33V3(a,b)) +////a*b +//#define M34MulM34(a,b) (_Mat34V::multiplyV(a,b)) +// a_rotation*b +//#define M34MulM33(a,b) (M34MulM33(a,b)) +// a_rotation*b_rotation +//#define M34Mul33MM34(a,b) (M34MulM33(a,b)) +// a+b +//#define M34Add(a,b) (M34Add(a,b)) +////a^-1 +//#define M34Inverse(a,b) (M34Inverse(a)) +// transpose(a_rotation) +//#define M34Trnsps33(a) (M33Trnsps3X3(a)) + +// Math operations on 16-byte aligned Mat44s (represents any 4x4 matrix) +// namespace _Mat44V +//{ +// //a*b +// PX_FORCE_INLINE Vec4V multiplyV(const Mat44V& a, const Vec4V b); +// //transpose(a)*b +// PX_FORCE_INLINE Vec4V multiplyTransposeV(const Mat44V& a, const Vec4V b); +// //a*b +// PX_FORCE_INLINE Mat44V multiplyV(const Mat44V& a, const Mat44V& b); +// //a+b +// PX_FORCE_INLINE Mat44V addV(const Mat44V& a, const Mat44V& b); +// //a&-1 +// PX_FORCE_INLINE Mat44V getInverseV(const Mat44V& a); +// //transpose(a) +// PX_FORCE_INLINE Mat44V getTransposeV(const Mat44V& a); +//}; //namespace _Mat44V + +// namespace _VecU32V +//{ +// // pack 8 U32s to 8 U16s with saturation +// PX_FORCE_INLINE VecU16V pack2U32VToU16VSaturate(VecU32V a, VecU32V b); +// PX_FORCE_INLINE VecU32V orV(VecU32V a, VecU32V b); +// PX_FORCE_INLINE VecU32V andV(VecU32V a, VecU32V b); +// PX_FORCE_INLINE VecU32V andcV(VecU32V a, VecU32V b); +// // conversion from integer to float +// PX_FORCE_INLINE Vec4V convertToVec4V(VecU32V a); +// // splat a[elementIndex] into all fields of a +// template +// PX_FORCE_INLINE VecU32V splatElement(VecU32V a); +// PX_FORCE_INLINE void storeAligned(VecU32V a, VecU32V* address); +//}; + +// namespace _VecI32V +//{ +// template PX_FORCE_INLINE VecI32V splatI32(); +//}; +// +// namespace _VecU16V +//{ +// PX_FORCE_INLINE VecU16V orV(VecU16V a, VecU16V b); +// PX_FORCE_INLINE VecU16V andV(VecU16V a, VecU16V b); +// PX_FORCE_INLINE VecU16V andcV(VecU16V a, VecU16V b); +// PX_FORCE_INLINE void storeAligned(VecU16V val, VecU16V *address); +// PX_FORCE_INLINE VecU16V loadAligned(VecU16V* addr); +// PX_FORCE_INLINE VecU16V loadUnaligned(VecU16V* addr); +// PX_FORCE_INLINE VecU16V compareGt(VecU16V a, VecU16V b); +// template +// PX_FORCE_INLINE VecU16V splatElement(VecU16V a); +// PX_FORCE_INLINE VecU16V subtractModulo(VecU16V a, VecU16V b); +// PX_FORCE_INLINE VecU16V addModulo(VecU16V a, VecU16V b); +// PX_FORCE_INLINE VecU32V getLo16(VecU16V a); // [0,2,4,6] 16-bit values to [0,1,2,3] 32-bit vector +// PX_FORCE_INLINE VecU32V getHi16(VecU16V a); // [1,3,5,7] 16-bit values to [0,1,2,3] 32-bit vector +//}; +// +// namespace _VecI16V +//{ +// template PX_FORCE_INLINE VecI16V splatImmediate(); +//}; +// +// namespace _VecU8V +//{ +//}; + +// a*b +//#define M44MulV4(a,b) (M44MulV4(a,b)) +////transpose(a)*b +//#define M44TrnspsMulV4(a,b) (M44TrnspsMulV4(a,b)) +////a*b +//#define M44MulM44(a,b) (M44MulM44(a,b)) +////a+b +//#define M44Add(a,b) (M44Add(a,b)) +////a&-1 +//#define M44Inverse(a) (M44Inverse(a)) +////transpose(a) +//#define M44Trnsps(a) (M44Trnsps(a)) + +// dsequeira: these used to be assert'd out in SIMD builds, but they're necessary if +// we want to be able to write some scalar functions which run using SIMD data structures + +PX_FORCE_INLINE void V3WriteX(Vec3V& v, const PxF32 f) +{ + reinterpret_cast(v).x = f; +} + +PX_FORCE_INLINE void V3WriteY(Vec3V& v, const PxF32 f) +{ + reinterpret_cast(v).y = f; +} + +PX_FORCE_INLINE void V3WriteZ(Vec3V& v, const PxF32 f) +{ + reinterpret_cast(v).z = f; +} + +PX_FORCE_INLINE void V3WriteXYZ(Vec3V& v, const PxVec3& f) +{ + reinterpret_cast(v) = f; +} + +PX_FORCE_INLINE PxF32 V3ReadX(const Vec3V& v) +{ + return reinterpret_cast(v).x; +} + +PX_FORCE_INLINE PxF32 V3ReadY(const Vec3V& v) +{ + return reinterpret_cast(v).y; +} + +PX_FORCE_INLINE PxF32 V3ReadZ(const Vec3V& v) +{ + return reinterpret_cast(v).z; +} + +PX_FORCE_INLINE const PxVec3& V3ReadXYZ(const Vec3V& v) +{ + return reinterpret_cast(v); +} + +PX_FORCE_INLINE void V4WriteX(Vec4V& v, const PxF32 f) +{ + reinterpret_cast(v).x = f; +} + +PX_FORCE_INLINE void V4WriteY(Vec4V& v, const PxF32 f) +{ + reinterpret_cast(v).y = f; +} + +PX_FORCE_INLINE void V4WriteZ(Vec4V& v, const PxF32 f) +{ + reinterpret_cast(v).z = f; +} + +PX_FORCE_INLINE void V4WriteW(Vec4V& v, const PxF32 f) +{ + reinterpret_cast(v).w = f; +} + +PX_FORCE_INLINE void V4WriteXYZ(Vec4V& v, const PxVec3& f) +{ + reinterpret_cast(v) = f; +} + +PX_FORCE_INLINE PxF32 V4ReadX(const Vec4V& v) +{ + return reinterpret_cast(v).x; +} + +PX_FORCE_INLINE PxF32 V4ReadY(const Vec4V& v) +{ + return reinterpret_cast(v).y; +} + +PX_FORCE_INLINE PxF32 V4ReadZ(const Vec4V& v) +{ + return reinterpret_cast(v).z; +} + +PX_FORCE_INLINE PxF32 V4ReadW(const Vec4V& v) +{ + return reinterpret_cast(v).w; +} + +PX_FORCE_INLINE const PxVec3& V4ReadXYZ(const Vec4V& v) +{ + return reinterpret_cast(v); +} + +// this macro transposes 4 Vec4V into 3 Vec4V (assuming that the W component can be ignored +#define PX_TRANSPOSE_44_34(inA, inB, inC, inD, outA, outB, outC) \ + \ +outA = V4UnpackXY(inA, inC); \ + \ +inA = V4UnpackZW(inA, inC); \ + \ +inC = V4UnpackXY(inB, inD); \ + \ +inB = V4UnpackZW(inB, inD); \ + \ +outB = V4UnpackZW(outA, inC); \ + \ +outA = V4UnpackXY(outA, inC); \ + \ +outC = V4UnpackXY(inA, inB); + +// this macro transposes 3 Vec4V into 4 Vec4V (with W components as garbage!) +#define PX_TRANSPOSE_34_44(inA, inB, inC, outA, outB, outC, outD) \ + outA = V4UnpackXY(inA, inC); \ + inA = V4UnpackZW(inA, inC); \ + outC = V4UnpackXY(inB, inB); \ + inC = V4UnpackZW(inB, inB); \ + outB = V4UnpackZW(outA, outC); \ + outA = V4UnpackXY(outA, outC); \ + outC = V4UnpackXY(inA, inC); \ + outD = V4UnpackZW(inA, inC); + +#define PX_TRANSPOSE_44(inA, inB, inC, inD, outA, outB, outC, outD) \ + outA = V4UnpackXY(inA, inC); \ + inA = V4UnpackZW(inA, inC); \ + inC = V4UnpackXY(inB, inD); \ + inB = V4UnpackZW(inB, inD); \ + outB = V4UnpackZW(outA, inC); \ + outA = V4UnpackXY(outA, inC); \ + outC = V4UnpackXY(inA, inB); \ + outD = V4UnpackZW(inA, inB); + +// This function returns a Vec4V, where each element is the dot product of one pair of Vec3Vs. On PC, each element in +// the result should be identical to the results if V3Dot was performed +// for each pair of Vec3V. +// However, on other platforms, the result might diverge by some small margin due to differences in FP rounding, e.g. if +// _mm_dp_ps was used or some other approximate dot product or fused madd operations +// were used. +// Where there does not exist a hw-accelerated dot-product operation, this approach should be the fastest way to compute +// the dot product of 4 vectors. +PX_FORCE_INLINE Vec4V V3Dot4(const Vec3VArg a0, const Vec3VArg b0, const Vec3VArg a1, const Vec3VArg b1, + const Vec3VArg a2, const Vec3VArg b2, const Vec3VArg a3, const Vec3VArg b3) +{ + Vec4V a0b0 = Vec4V_From_Vec3V(V3Mul(a0, b0)); + Vec4V a1b1 = Vec4V_From_Vec3V(V3Mul(a1, b1)); + Vec4V a2b2 = Vec4V_From_Vec3V(V3Mul(a2, b2)); + Vec4V a3b3 = Vec4V_From_Vec3V(V3Mul(a3, b3)); + + Vec4V aTrnsps, bTrnsps, cTrnsps; + + PX_TRANSPOSE_44_34(a0b0, a1b1, a2b2, a3b3, aTrnsps, bTrnsps, cTrnsps); + + return V4Add(V4Add(aTrnsps, bTrnsps), cTrnsps); +} + +//(f.x,f.y,f.z,0) - Alternative/faster V3LoadU implementation when it is safe to read "W", i.e. the 32bits after the PxVec3. +PX_FORCE_INLINE Vec3V V3LoadU_SafeReadW(const PxVec3& f) +{ + return Vec3V_From_Vec4V(V4LoadU(&f.x)); +} + +} // namespace aos +} // namespace shdfnd +} // namespace physx + +// Now for the cross-platform implementations of the 16-byte aligned maths functions (win32/360/ppu/spu etc). +#if COMPILE_VECTOR_INTRINSICS +#include "PsInlineAoS.h" +#else // #if COMPILE_VECTOR_INTRINSICS +#include "PsVecMathAoSScalarInline.h" +#endif // #if !COMPILE_VECTOR_INTRINSICS +#include "PsVecQuat.h" + +#endif // PSFOUNDATION_PSVECMATH_H diff --git a/sources/PhysX/PhysX/source/foundation/include/PsVecMathAoSScalar.h b/sources/PhysX/PhysX/source/foundation/include/PsVecMathAoSScalar.h new file mode 100644 index 00000000..ba2b63ed --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsVecMathAoSScalar.h @@ -0,0 +1,250 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSVECMATHAOSSCALAR_H +#define PSFOUNDATION_PSVECMATHAOSSCALAR_H + +#if COMPILE_VECTOR_INTRINSICS +#error Scalar version should not be included when using vector intrinsics. +#endif + +namespace physx +{ +namespace shdfnd +{ +namespace aos +{ + +struct VecI16V; +struct VecU16V; +struct VecI32V; +struct VecU32V; +struct Vec4V; +typedef Vec4V QuatV; + +PX_ALIGN_PREFIX(16) +struct FloatV +{ + PxF32 x; + PxF32 pad[3]; + FloatV() + { + } + FloatV(const PxF32 _x) : x(_x) + { + } +} PX_ALIGN_SUFFIX(16); + +PX_ALIGN_PREFIX(16) +struct Vec4V +{ + PxF32 x, y, z, w; + Vec4V() + { + } + Vec4V(const PxF32 _x, const PxF32 _y, const PxF32 _z, const PxF32 _w) : x(_x), y(_y), z(_z), w(_w) + { + } +} PX_ALIGN_SUFFIX(16); + +PX_ALIGN_PREFIX(16) +struct Vec3V +{ + PxF32 x, y, z; + PxF32 pad; + Vec3V() + { + } + Vec3V(const PxF32 _x, const PxF32 _y, const PxF32 _z) : x(_x), y(_y), z(_z), pad(0.0f) + { + } +} PX_ALIGN_SUFFIX(16); + +PX_ALIGN_PREFIX(16) +struct BoolV +{ + PxU32 ux, uy, uz, uw; + BoolV() + { + } + BoolV(const PxU32 _x, const PxU32 _y, const PxU32 _z, const PxU32 _w) : ux(_x), uy(_y), uz(_z), uw(_w) + { + } +} PX_ALIGN_SUFFIX(16); + +struct Mat33V +{ + Mat33V() + { + } + Mat33V(const Vec3V& c0, const Vec3V& c1, const Vec3V& c2) : col0(c0), col1(c1), col2(c2) + { + } + Vec3V col0; + Vec3V col1; + Vec3V col2; +}; + +struct Mat34V +{ + Mat34V() + { + } + Mat34V(const Vec3V& c0, const Vec3V& c1, const Vec3V& c2, const Vec3V& c3) : col0(c0), col1(c1), col2(c2), col3(c3) + { + } + Vec3V col0; + Vec3V col1; + Vec3V col2; + Vec3V col3; +}; + +struct Mat43V +{ + Mat43V() + { + } + Mat43V(const Vec4V& c0, const Vec4V& c1, const Vec4V& c2) : col0(c0), col1(c1), col2(c2) + { + } + Vec4V col0; + Vec4V col1; + Vec4V col2; +}; + +struct Mat44V +{ + Mat44V() + { + } + Mat44V(const Vec4V& c0, const Vec4V& c1, const Vec4V& c2, const Vec4V& c3) : col0(c0), col1(c1), col2(c2), col3(c3) + { + } + Vec4V col0; + Vec4V col1; + Vec4V col2; + Vec4V col3; +}; + +PX_ALIGN_PREFIX(16) +struct VecU32V +{ + PxU32 u32[4]; + PX_FORCE_INLINE VecU32V() + { + } + PX_FORCE_INLINE VecU32V(PxU32 a, PxU32 b, PxU32 c, PxU32 d) + { + u32[0] = a; + u32[1] = b; + u32[2] = c; + u32[3] = d; + } +} PX_ALIGN_SUFFIX(16); + +PX_ALIGN_PREFIX(16) +struct VecI32V +{ + PxI32 i32[4]; + PX_FORCE_INLINE VecI32V() + { + } + PX_FORCE_INLINE VecI32V(PxI32 a, PxI32 b, PxI32 c, PxI32 d) + { + i32[0] = a; + i32[1] = b; + i32[2] = c; + i32[3] = d; + } +} PX_ALIGN_SUFFIX(16); + +PX_ALIGN_PREFIX(16) +struct VecI16V +{ + PxI16 i16[8]; + PX_FORCE_INLINE VecI16V() + { + } + PX_FORCE_INLINE VecI16V(PxI16 a, PxI16 b, PxI16 c, PxI16 d, PxI16 e, PxI16 f, PxI16 g, PxI16 h) + { + i16[0] = a; + i16[1] = b; + i16[2] = c; + i16[3] = d; + i16[4] = e; + i16[5] = f; + i16[6] = g; + i16[7] = h; + } +} PX_ALIGN_SUFFIX(16); + +PX_ALIGN_PREFIX(16) +struct VecU16V +{ + union + { + PxU16 u16[8]; + PxI16 i16[8]; + }; + PX_FORCE_INLINE VecU16V() + { + } + PX_FORCE_INLINE VecU16V(PxU16 a, PxU16 b, PxU16 c, PxU16 d, PxU16 e, PxU16 f, PxU16 g, PxU16 h) + { + u16[0] = a; + u16[1] = b; + u16[2] = c; + u16[3] = d; + u16[4] = e; + u16[5] = f; + u16[6] = g; + u16[7] = h; + } +} PX_ALIGN_SUFFIX(16); + +#define FloatVArg FloatV & +#define Vec3VArg Vec3V & +#define Vec4VArg Vec4V & +#define BoolVArg BoolV & +#define VecU32VArg VecU32V & +#define VecI32VArg VecI32V & +#define VecU16VArg VecU16V & +#define VecI16VArg VecI16V & +#define QuatVArg QuatV & + +#define VecCrossV Vec3V + +typedef VecI32V VecShiftV; +#define VecShiftVArg VecShiftV & + +} // namespace aos +} // namespace shdfnd +} // namespace physx + +#endif // PX_PHYSICS_COMMON_VECMATH_INLINE_SCALAR diff --git a/sources/PhysX/PhysX/source/foundation/include/PsVecMathAoSScalarInline.h b/sources/PhysX/PhysX/source/foundation/include/PsVecMathAoSScalarInline.h new file mode 100644 index 00000000..1e2e65c1 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsVecMathAoSScalarInline.h @@ -0,0 +1,2275 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSVECMATHAOSSCALARINLINE_H +#define PSFOUNDATION_PSVECMATHAOSSCALARINLINE_H + +#if COMPILE_VECTOR_INTRINSICS +#error Scalar version should not be included when using vector intrinsics. +#endif + +namespace physx +{ +namespace shdfnd +{ +namespace aos +{ + +#define BOOL_TO_U32(b) (PxU32)(- PxI32(b)) +#define TRUE_TO_U32 (PxU32)(-1) +#define FALSE_TO_U32 (PxU32)(0) + +#define BOOL_TO_U16(b) (PxU16)(- PxI32(b)) + +#define PX_VECMATH_ASSERT_ENABLED 0 + +#if PX_VECMATH_ASSERT_ENABLED +#define VECMATHAOS_ASSERT(x) { PX_ASSERT(x); } +#else +#define VECMATHAOS_ASSERT(x) +#endif + +///////////////////////////////////////////////////////////////////// +////INTERNAL USE ONLY AND TESTS +///////////////////////////////////////////////////////////////////// + +namespace internalScalarSimd +{ +PX_FORCE_INLINE PxF32 FStore(const FloatV a) +{ + return a.x; +} + +PX_FORCE_INLINE bool hasZeroElementInFloatV(const FloatV a) +{ + return (0 == a.x); +} + +PX_FORCE_INLINE bool hasZeroElementInVec3V(const Vec3V a) +{ + return (0 == a.x || 0 == a.y || 0 == a.z); +} + +PX_FORCE_INLINE bool hasZeroElementInVec4V(const Vec4V a) +{ + return (0 == a.x || 0 == a.y || 0 == a.z || 0 == a.w); +} +} + +namespace _VecMathTests +{ +// PT: this function returns an invalid Vec3V (W!=0.0f) just for unit-testing 'isValidVec3V' +PX_FORCE_INLINE Vec3V getInvalidVec3V() +{ + Vec3V tmp; + tmp.x = tmp.y = tmp.z = 0.0f; + tmp.pad = 1.0f; + return tmp; +} + +PX_FORCE_INLINE bool allElementsEqualFloatV(const FloatV a, const FloatV b) +{ + return (a.x == b.x); +} + +PX_FORCE_INLINE bool allElementsEqualVec3V(const Vec3V a, const Vec3V b) +{ + return (a.x == b.x && a.y == b.y && a.z == b.z); +} + +PX_FORCE_INLINE bool allElementsEqualVec4V(const Vec4V a, const Vec4V b) +{ + return (a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w); +} + +PX_FORCE_INLINE bool allElementsEqualBoolV(const BoolV a, const BoolV b) +{ + return (a.ux == b.ux && a.uy == b.uy && a.uz == b.uz && a.uw == b.uw); +} + +PX_FORCE_INLINE bool allElementsEqualVecU32V(const VecU32V a, const VecU32V b) +{ + return (a.u32[0] == b.u32[0] && a.u32[1] == b.u32[1] && a.u32[2] == b.u32[2] && a.u32[3] == b.u32[3]); +} + +PX_FORCE_INLINE bool allElementsEqualVecI32V(const VecI32V a, const VecI32V b) +{ + return (a.i32[0] == b.i32[0] && a.i32[1] == b.i32[1] && a.i32[2] == b.i32[2] && a.i32[3] == b.i32[3]); +} + +#define VECMATH_AOS_EPSILON (1e-3f) + +PX_FORCE_INLINE bool allElementsNearEqualFloatV(const FloatV a, const FloatV b) +{ + const PxF32 cx = a.x - b.x; + return (cx > -VECMATH_AOS_EPSILON && cx < VECMATH_AOS_EPSILON); +} + +PX_FORCE_INLINE bool allElementsNearEqualVec3V(const Vec3V a, const Vec3V b) +{ + const PxF32 cx = a.x - b.x; + const PxF32 cy = a.y - b.y; + const PxF32 cz = a.z - b.z; + return (cx > -VECMATH_AOS_EPSILON && cx < VECMATH_AOS_EPSILON && cy > -VECMATH_AOS_EPSILON && + cy < VECMATH_AOS_EPSILON && cz > -VECMATH_AOS_EPSILON && cz < VECMATH_AOS_EPSILON); +} + +PX_FORCE_INLINE bool allElementsNearEqualVec4V(const Vec4V a, const Vec4V b) +{ + const PxF32 cx = a.x - b.x; + const PxF32 cy = a.y - b.y; + const PxF32 cz = a.z - b.z; + const PxF32 cw = a.w - b.w; + return (cx > -VECMATH_AOS_EPSILON && cx < VECMATH_AOS_EPSILON && cy > -VECMATH_AOS_EPSILON && + cy < VECMATH_AOS_EPSILON && cz > -VECMATH_AOS_EPSILON && cz < VECMATH_AOS_EPSILON && + cw > -VECMATH_AOS_EPSILON && cw < VECMATH_AOS_EPSILON); +} +} + +/////////////////////////////////////////////////////// + +PX_FORCE_INLINE bool isValidVec3V(const Vec3V a) +{ + return a.pad == 0.f; +} + +PX_FORCE_INLINE bool isFiniteFloatV(const FloatV a) +{ + return PxIsFinite(a.x); +} + +PX_FORCE_INLINE bool isFiniteVec3V(const Vec3V a) +{ + return PxIsFinite(a.x) && PxIsFinite(a.y) && PxIsFinite(a.z); +} + +PX_FORCE_INLINE bool isFiniteVec4V(const Vec4V a) +{ + return PxIsFinite(a.x) && PxIsFinite(a.y) && PxIsFinite(a.z) && PxIsFinite(a.w); +} + +///////////////////////////////////////////////////////////////////// +////VECTORISED FUNCTION IMPLEMENTATIONS +///////////////////////////////////////////////////////////////////// + +PX_FORCE_INLINE FloatV FLoad(const PxF32 f) +{ + return FloatV(f); +} + +PX_FORCE_INLINE Vec3V V3Load(const PxF32 f) +{ + return Vec3V(f, f, f); +} + +PX_FORCE_INLINE Vec4V V4Load(const PxF32 f) +{ + return Vec4V(f, f, f, f); +} + +PX_FORCE_INLINE BoolV BLoad(const bool f) +{ +#if PX_ARM + // SD: Android ARM builds fail if this is done with a cast. + // Might also fail because of something else but the select + // operator here seems to fix everything that failed in release builds. + return f ? BTTTT() : BFFFF(); +#else + return BoolV(BOOL_TO_U32(f), BOOL_TO_U32(f), BOOL_TO_U32(f), BOOL_TO_U32(f)); +#endif +} + +PX_FORCE_INLINE Vec3V V3LoadA(const PxVec3& f) +{ + return Vec3V(f.x, f.y, f.z); +} + +PX_FORCE_INLINE Vec3V V3LoadU(const PxVec3& f) +{ + return Vec3V(f.x, f.y, f.z); +} + +PX_FORCE_INLINE Vec3V V3LoadUnsafeA(const PxVec3& f) +{ + return Vec3V(f.x, f.y, f.z); +} + +PX_FORCE_INLINE Vec3V V3LoadA(const PxF32* const f) +{ + return Vec3V(f[0], f[1], f[2]); +} + +PX_FORCE_INLINE Vec3V V3LoadU(const PxF32* const f) +{ + return Vec3V(f[0], f[1], f[2]); +} + +PX_FORCE_INLINE Vec3V Vec3V_From_Vec4V(Vec4V f) +{ + return Vec3V(f.x, f.y, f.z); +} + +PX_FORCE_INLINE Vec3V Vec3V_From_Vec4V_WUndefined(const Vec4V v) +{ + return Vec3V(v.x, v.y, v.z); +} + +PX_FORCE_INLINE Vec4V Vec4V_From_Vec3V(Vec3V f) +{ + return Vec4V(f.x, f.y, f.z, 0.0f); +} + +PX_FORCE_INLINE Vec4V Vec4V_From_FloatV(FloatV f) +{ + return Vec4V(f.x, f.x, f.x, f.x); +} + +PX_FORCE_INLINE Vec3V Vec3V_From_FloatV(FloatV f) +{ + return Vec3V(f.x, f.x, f.x); +} + +PX_FORCE_INLINE Vec3V Vec3V_From_FloatV_WUndefined(FloatV f) +{ + return Vec3V(f.x, f.x, f.x); +} + +PX_FORCE_INLINE Vec4V V4LoadA(const PxF32* const f) +{ + return Vec4V(f[0], f[1], f[2], f[3]); +} + +PX_FORCE_INLINE void V4StoreA(const Vec4V a, PxF32* f) +{ + *reinterpret_cast(f) = a; +} + +PX_FORCE_INLINE void V4StoreU(const Vec4V a, PxF32* f) +{ + *reinterpret_cast(f) = *reinterpret_cast(&a.x); +} + +PX_FORCE_INLINE void BStoreA(const BoolV a, PxU32* f) +{ + *reinterpret_cast(f) = a; +} + +PX_FORCE_INLINE void U4StoreA(const VecU32V uv, PxU32* u) +{ + *reinterpret_cast(u) = uv; +} + +PX_FORCE_INLINE void I4StoreA(const VecI32V iv, PxI32* i) +{ + *reinterpret_cast(i) = iv; +} + +PX_FORCE_INLINE Vec4V V4LoadU(const PxF32* const f) +{ + return Vec4V(f[0], f[1], f[2], f[3]); +} + +PX_FORCE_INLINE Vec4V Vec4V_From_PxVec3_WUndefined(const PxVec3& f) +{ + return Vec4V(f[0], f[1], f[2], 0.0f); +} + +PX_FORCE_INLINE BoolV BLoad(const bool* const f) +{ + return BoolV(BOOL_TO_U32(f[0]), BOOL_TO_U32(f[1]), BOOL_TO_U32(f[2]), BOOL_TO_U32(f[3])); +} + +PX_FORCE_INLINE void FStore(const FloatV a, PxF32* PX_RESTRICT f) +{ + *f = a.x; +} + +PX_FORCE_INLINE void V3StoreA(const Vec3V a, PxVec3& f) +{ + f = PxVec3(a.x, a.y, a.z); +} + +PX_FORCE_INLINE void V3StoreU(const Vec3V a, PxVec3& f) +{ + f = PxVec3(a.x, a.y, a.z); +} + +PX_FORCE_INLINE void Store_From_BoolV(const BoolV b, PxU32* b2) +{ + *b2 = b.ux; +} + +////////////////////////// +// FLOATV +////////////////////////// + +PX_FORCE_INLINE FloatV FZero() +{ + return FLoad(0.0f); +} + +PX_FORCE_INLINE FloatV FOne() +{ + return FLoad(1.0f); +} + +PX_FORCE_INLINE FloatV FHalf() +{ + return FLoad(0.5f); +} + +PX_FORCE_INLINE FloatV FEps() +{ + return FLoad(PX_EPS_REAL); +} + +PX_FORCE_INLINE FloatV FEps6() +{ + return FLoad(1e-6f); +} + +PX_FORCE_INLINE FloatV FMax() +{ + return FLoad(PX_MAX_REAL); +} + +PX_FORCE_INLINE FloatV FNegMax() +{ + return FLoad(-PX_MAX_REAL); +} + +PX_FORCE_INLINE FloatV FNeg(const FloatV f) +{ + return FloatV(-f.x); +} + +PX_FORCE_INLINE FloatV FAdd(const FloatV a, const FloatV b) +{ + return FloatV(a.x + b.x); +} + +PX_FORCE_INLINE FloatV FSub(const FloatV a, const FloatV b) +{ + return FloatV(a.x - b.x); +} + +PX_FORCE_INLINE FloatV FMul(const FloatV a, const FloatV b) +{ + return FloatV(a.x * b.x); +} + +PX_FORCE_INLINE FloatV FDiv(const FloatV a, const FloatV b) +{ + VECMATHAOS_ASSERT(b.x != 0.0f); + return FloatV(a.x / b.x); +} + +PX_FORCE_INLINE FloatV FDivFast(const FloatV a, const FloatV b) +{ + VECMATHAOS_ASSERT(b.x != 0.0f); + return FloatV(a.x / b.x); +} + +PX_FORCE_INLINE FloatV FRecip(const FloatV a) +{ + VECMATHAOS_ASSERT(a.x != 0.0f); + return 1.0f / a.x; +} + +PX_FORCE_INLINE FloatV FRecipFast(const FloatV a) +{ + VECMATHAOS_ASSERT(a.x != 0.0f); + return 1.0f / a.x; +} + +PX_FORCE_INLINE FloatV FRsqrt(const FloatV a) +{ + VECMATHAOS_ASSERT(a.x != 0.0f); + return PxRecipSqrt(a.x); +} + +PX_FORCE_INLINE FloatV FSqrt(const FloatV a) +{ + return PxSqrt(a.x); +} + +PX_FORCE_INLINE FloatV FRsqrtFast(const FloatV a) +{ + VECMATHAOS_ASSERT(a.x != 0.0f); + return PxRecipSqrt(a.x); +} + +PX_FORCE_INLINE FloatV FScaleAdd(const FloatV a, const FloatV b, const FloatV c) +{ + return FAdd(FMul(a, b), c); +} + +PX_FORCE_INLINE FloatV FNegScaleSub(const FloatV a, const FloatV b, const FloatV c) +{ + return FSub(c, FMul(a, b)); +} + +PX_FORCE_INLINE FloatV FAbs(const FloatV a) +{ + return FloatV(PxAbs(a.x)); +} + +PX_FORCE_INLINE FloatV FSel(const BoolV c, const FloatV a, const FloatV b) +{ + return FloatV(c.ux ? a.x : b.x); +} + +PX_FORCE_INLINE BoolV FIsGrtr(const FloatV a, const FloatV b) +{ + return BLoad(a.x > b.x); +} + +PX_FORCE_INLINE BoolV FIsGrtrOrEq(const FloatV a, const FloatV b) +{ + return BLoad(a.x >= b.x); +} + +PX_FORCE_INLINE BoolV FIsEq(const FloatV a, const FloatV b) +{ + return BLoad(a.x == b.x); +} + +PX_FORCE_INLINE FloatV FMax(const FloatV a, const FloatV b) +{ + return (a.x > b.x ? FloatV(a.x) : FloatV(b.x)); +} + +PX_FORCE_INLINE FloatV FMin(const FloatV a, const FloatV b) +{ + return (a.x > b.x ? FloatV(b.x) : FloatV(a.x)); +} + +PX_FORCE_INLINE FloatV FClamp(const FloatV a, const FloatV minV, const FloatV maxV) +{ + return FMax(FMin(a, maxV), minV); +} + +PX_FORCE_INLINE PxU32 FAllGrtr(const FloatV a, const FloatV b) +{ + return BOOL_TO_U32(a.x > b.x); +} + +PX_FORCE_INLINE PxU32 FAllGrtrOrEq(const FloatV a, const FloatV b) +{ + return BOOL_TO_U32(a.x >= b.x); +} +PX_FORCE_INLINE PxU32 FAllEq(const FloatV a, const FloatV b) +{ + return BOOL_TO_U32(a.x == b.x); +} + +PX_FORCE_INLINE FloatV FRound(const FloatV a) +{ + return floorf(a.x + 0.5f); +} + +PX_FORCE_INLINE FloatV FSin(const FloatV a) +{ + return sinf(a.x); +} + +PX_FORCE_INLINE FloatV FCos(const FloatV a) +{ + return cosf(a.x); +} + +PX_FORCE_INLINE PxU32 FOutOfBounds(const FloatV a, const FloatV min, const FloatV max) +{ + return BOOL_TO_U32(a.x > max.x || a.x < min.x); +} + +PX_FORCE_INLINE PxU32 FInBounds(const FloatV a, const FloatV min, const FloatV max) +{ + return BOOL_TO_U32(a.x >= min.x && a.x <= max.x); +} + +PX_FORCE_INLINE PxU32 FOutOfBounds(const FloatV a, const FloatV bounds) +{ + return FOutOfBounds(a, FNeg(bounds), bounds); +} + +PX_FORCE_INLINE PxU32 FInBounds(const FloatV a, const FloatV bounds) +{ + return FInBounds(a, FNeg(bounds), bounds); +} + +///////////////////// +// VEC3V +///////////////////// + +PX_FORCE_INLINE Vec3V V3Splat(const FloatV f) +{ + return Vec3V(f.x, f.x, f.x); +} + +PX_FORCE_INLINE Vec3V V3Merge(const FloatVArg x, const FloatVArg y, const FloatVArg z) +{ + return Vec3V(x.x, y.x, z.x); +} + +PX_FORCE_INLINE Vec3V V3UnitX() +{ + return Vec3V(1.0f, 0.0f, 0.0f); +} + +PX_FORCE_INLINE Vec3V V3UnitY() +{ + return Vec3V(0.0f, 1.0f, 0.0f); +} + +PX_FORCE_INLINE Vec3V V3UnitZ() +{ + return Vec3V(0.0f, 0.0f, 1.0f); +} + +PX_FORCE_INLINE FloatV V3GetX(const Vec3V f) +{ + return FloatV(f.x); +} + +PX_FORCE_INLINE FloatV V3GetY(const Vec3V f) +{ + return FloatV(f.y); +} + +PX_FORCE_INLINE FloatV V3GetZ(const Vec3V f) +{ + return FloatV(f.z); +} + +PX_FORCE_INLINE Vec3V V3SetX(const Vec3V v, const FloatV f) +{ + return Vec3V(f.x, v.y, v.z); +} + +PX_FORCE_INLINE Vec3V V3SetY(const Vec3V v, const FloatV f) +{ + return Vec3V(v.x, f.x, v.z); +} + +PX_FORCE_INLINE Vec3V V3SetZ(const Vec3V v, const FloatV f) +{ + return Vec3V(v.x, v.y, f.x); +} + +PX_FORCE_INLINE Vec3V V3ColX(const Vec3V a, const Vec3V b, const Vec3V c) +{ + return Vec3V(a.x, b.x, c.x); +} + +PX_FORCE_INLINE Vec3V V3ColY(const Vec3V a, const Vec3V b, const Vec3V c) +{ + return Vec3V(a.y, b.y, c.y); +} + +PX_FORCE_INLINE Vec3V V3ColZ(const Vec3V a, const Vec3V b, const Vec3V c) +{ + return Vec3V(a.z, b.z, c.z); +} + +PX_FORCE_INLINE Vec3V V3Zero() +{ + return V3Load(0.0f); +} + +PX_FORCE_INLINE Vec3V V3One() +{ + return V3Load(1.0f); +} + +PX_FORCE_INLINE Vec3V V3Eps() +{ + return V3Load(PX_EPS_REAL); +} + +PX_FORCE_INLINE Vec3V V3Neg(const Vec3V c) +{ + return Vec3V(-c.x, -c.y, -c.z); +} + +PX_FORCE_INLINE Vec3V V3Add(const Vec3V a, const Vec3V b) +{ + return Vec3V(a.x + b.x, a.y + b.y, a.z + b.z); +} + +PX_FORCE_INLINE Vec3V V3Sub(const Vec3V a, const Vec3V b) +{ + return Vec3V(a.x - b.x, a.y - b.y, a.z - b.z); +} + +PX_FORCE_INLINE Vec3V V3Scale(const Vec3V a, const FloatV b) +{ + return Vec3V(a.x * b.x, a.y * b.x, a.z * b.x); +} + +PX_FORCE_INLINE Vec3V V3Mul(const Vec3V a, const Vec3V b) +{ + return Vec3V(a.x * b.x, a.y * b.y, a.z * b.z); +} + +PX_FORCE_INLINE Vec3V V3ScaleInv(const Vec3V a, const FloatV b) +{ + const PxF32 bInv = 1.0f / b.x; + return Vec3V(a.x * bInv, a.y * bInv, a.z * bInv); +} + +PX_FORCE_INLINE Vec3V V3Div(const Vec3V a, const Vec3V b) +{ + return Vec3V(a.x / b.x, a.y / b.y, a.z / b.z); +} + +PX_FORCE_INLINE Vec3V V3ScaleInvFast(const Vec3V a, const FloatV b) +{ + const PxF32 bInv = 1.0f / b.x; + return Vec3V(a.x * bInv, a.y * bInv, a.z * bInv); +} + +PX_FORCE_INLINE Vec3V V3DivFast(const Vec3V a, const Vec3V b) +{ + return Vec3V(a.x / b.x, a.y / b.y, a.z / b.z); +} + +PX_FORCE_INLINE Vec3V V3Recip(const Vec3V a) +{ + return Vec3V(1.0f / a.x, 1.0f / a.y, 1.0f / a.z); +} + +PX_FORCE_INLINE Vec3V V3RecipFast(const Vec3V a) +{ + return Vec3V(1.0f / a.x, 1.0f / a.y, 1.0f / a.z); +} + +PX_FORCE_INLINE Vec3V V3Rsqrt(const Vec3V a) +{ + return Vec3V(PxRecipSqrt(a.x), PxRecipSqrt(a.y), PxRecipSqrt(a.z)); +} + +PX_FORCE_INLINE Vec3V V3RsqrtFast(const Vec3V a) +{ + return Vec3V(PxRecipSqrt(a.x), PxRecipSqrt(a.y), PxRecipSqrt(a.z)); +} + +PX_FORCE_INLINE Vec3V V3ScaleAdd(const Vec3V a, const FloatV b, const Vec3V c) +{ + return V3Add(V3Scale(a, b), c); +} + +PX_FORCE_INLINE Vec3V V3NegScaleSub(const Vec3V a, const FloatV b, const Vec3V c) +{ + return V3Sub(c, V3Scale(a, b)); +} + +PX_FORCE_INLINE Vec3V V3MulAdd(const Vec3V a, const Vec3V b, const Vec3V c) +{ + return V3Add(V3Mul(a, b), c); +} + +PX_FORCE_INLINE Vec3V V3NegMulSub(const Vec3V a, const Vec3V b, const Vec3V c) +{ + return V3Sub(c, V3Mul(a, b)); +} + +PX_FORCE_INLINE FloatV V3Dot(const Vec3V a, const Vec3V b) +{ + return FloatV(a.x * b.x + a.y * b.y + a.z * b.z); +} + +PX_FORCE_INLINE VecCrossV V3PrepareCross(const Vec3VArg normal) +{ + return normal; +} + +PX_FORCE_INLINE Vec3V V3Cross(const Vec3V a, const Vec3V b) +{ + return Vec3V(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x); +} + +PX_FORCE_INLINE FloatV V3Length(const Vec3V a) +{ + return FloatV(PxSqrt(a.x * a.x + a.y * a.y + a.z * a.z)); +} + +PX_FORCE_INLINE FloatV V3LengthSq(const Vec3V a) +{ + return FloatV(a.x * a.x + a.y * a.y + a.z * a.z); +} + +PX_FORCE_INLINE Vec3V V3Normalize(const Vec3V a) +{ + VECMATHAOS_ASSERT(a.x != 0 || a.y != 0 || a.z != 0); + const PxF32 lengthInv = 1.0f / PxSqrt(a.x * a.x + a.y * a.y + a.z * a.z); + return Vec3V(a.x * lengthInv, a.y * lengthInv, a.z * lengthInv); +} + +PX_FORCE_INLINE Vec3V V3NormalizeSafe(const Vec3V a, const Vec3V unsafeReturnValue) +{ + const PxF32 length = PxSqrt(a.x * a.x + a.y * a.y + a.z * a.z); + if(PX_EPS_REAL >= length) + { + return unsafeReturnValue; + } + else + { + const PxF32 lengthInv = 1.0f / length; + return Vec3V(a.x * lengthInv, a.y * lengthInv, a.z * lengthInv); + } +} + +PX_FORCE_INLINE Vec3V V3NormalizeFast(const Vec3V a) +{ + VECMATHAOS_ASSERT(a.x != 0 || a.y != 0 || a.z != 0); + const PxF32 lengthInv = 1.0f / PxSqrt(a.x * a.x + a.y * a.y + a.z * a.z); + return Vec3V(a.x * lengthInv, a.y * lengthInv, a.z * lengthInv); +} + +PX_FORCE_INLINE Vec3V V3Sel(const BoolV c, const Vec3V a, const Vec3V b) +{ + return Vec3V(c.ux ? a.x : b.x, c.uy ? a.y : b.y, c.uz ? a.z : b.z); +} + +PX_FORCE_INLINE BoolV V3IsGrtr(const Vec3V a, const Vec3V b) +{ + return BoolV(BOOL_TO_U32(a.x > b.x), BOOL_TO_U32(a.y > b.y), BOOL_TO_U32(a.z > b.z), FALSE_TO_U32); +} + +PX_FORCE_INLINE BoolV V3IsGrtrOrEq(const Vec3V a, const Vec3V b) +{ + return BoolV(BOOL_TO_U32(a.x >= b.x), BOOL_TO_U32(a.y >= b.y), BOOL_TO_U32(a.z >= b.z), TRUE_TO_U32); +} + +PX_FORCE_INLINE BoolV V3IsEq(const Vec3V a, const Vec3V b) +{ + return BoolV(BOOL_TO_U32(a.x == b.x), BOOL_TO_U32(a.y == b.y), BOOL_TO_U32(a.z == b.z), TRUE_TO_U32); +} + +PX_FORCE_INLINE Vec3V V3Max(const Vec3V a, const Vec3V b) +{ + return Vec3V(a.x > b.x ? a.x : b.x, a.y > b.y ? a.y : b.y, a.z > b.z ? a.z : b.z); +} + +PX_FORCE_INLINE Vec3V V3Min(const Vec3V a, const Vec3V b) +{ + return Vec3V(a.x < b.x ? a.x : b.x, a.y < b.y ? a.y : b.y, a.z < b.z ? a.z : b.z); +} + +PX_FORCE_INLINE FloatV V3ExtractMax(const Vec3V a) +{ + const PxF32 t0 = (a.x >= a.y) ? a.x : a.y; + return t0 >= a.z ? t0 : a.z; +} + +PX_FORCE_INLINE FloatV V3ExtractMin(const Vec3V a) +{ + const PxF32 t0 = (a.x <= a.y) ? a.x : a.y; + return t0 <= a.z ? t0 : a.z; +} + +// return (a >= 0.0f) ? 1.0f : -1.0f; +PX_FORCE_INLINE Vec3V V3Sign(const Vec3V a) +{ + return Vec3V((a.x >= 0.f ? 1.f : -1.f), (a.y >= 0.f ? 1.f : -1.f), (a.z >= 0.f ? 1.f : -1.f)); +} + +PX_FORCE_INLINE Vec3V V3Clamp(const Vec3V a, const Vec3V minV, const Vec3V maxV) +{ + return V3Max(V3Min(a, maxV), minV); +} + +PX_FORCE_INLINE Vec3V V3Abs(const Vec3V a) +{ + return V3Max(a, V3Neg(a)); +} + +PX_FORCE_INLINE PxU32 V3AllGrtr(const Vec3V a, const Vec3V b) +{ + return BOOL_TO_U32((a.x > b.x) & (a.y > b.y) & (a.z > b.z)); +} + +PX_FORCE_INLINE PxU32 V3AllGrtrOrEq(const Vec3V a, const Vec3V b) +{ + return BOOL_TO_U32((a.x >= b.x) & (a.y >= b.y) & (a.z >= b.z)); +} + +PX_FORCE_INLINE PxU32 V3AllEq(const Vec3V a, const Vec3V b) +{ + return BOOL_TO_U32((a.x == b.x) & (a.y == b.y) & (a.z == b.z)); +} + +PX_FORCE_INLINE Vec3V V3Round(const Vec3V a) +{ + return Vec3V(floorf(a.x + 0.5f), floorf(a.y + 0.5f), floorf(a.z + 0.5f)); +} + +PX_FORCE_INLINE Vec3V V3Sin(const Vec3V a) +{ + return Vec3V(sinf(a.x), sinf(a.y), sinf(a.z)); +} + +PX_FORCE_INLINE Vec3V V3Cos(const Vec3V a) +{ + return Vec3V(cosf(a.x), cosf(a.y), cosf(a.z)); +} + +PX_FORCE_INLINE Vec3V V3PermYZZ(const Vec3V a) +{ + return Vec3V(a.y, a.z, a.z); +} + +PX_FORCE_INLINE Vec3V V3PermXYX(const Vec3V a) +{ + return Vec3V(a.x, a.y, a.x); +} + +PX_FORCE_INLINE Vec3V V3PermYZX(const Vec3V a) +{ + return Vec3V(a.y, a.z, a.x); +} + +PX_FORCE_INLINE Vec3V V3PermZXY(const Vec3V a) +{ + return Vec3V(a.z, a.x, a.y); +} + +PX_FORCE_INLINE Vec3V V3PermZZY(const Vec3V a) +{ + return Vec3V(a.z, a.z, a.y); +} + +PX_FORCE_INLINE Vec3V V3PermYXX(const Vec3V a) +{ + return Vec3V(a.y, a.x, a.x); +} + +PX_FORCE_INLINE Vec3V V3Perm_Zero_1Z_0Y(const Vec3V v0, const Vec3V v1) +{ + return Vec3V(0.0f, v1.z, v0.y); +} + +PX_FORCE_INLINE Vec3V V3Perm_0Z_Zero_1X(const Vec3V v0, const Vec3V v1) +{ + return Vec3V(v0.z, 0.0f, v1.x); +} + +PX_FORCE_INLINE Vec3V V3Perm_1Y_0X_Zero(const Vec3V v0, const Vec3V v1) +{ + return Vec3V(v1.y, v0.x, 0.0f); +} + +PX_FORCE_INLINE FloatV V3SumElems(const Vec3V a) +{ + return FloatV(a.x + a.y + a.z); +} + +PX_FORCE_INLINE PxU32 V3OutOfBounds(const Vec3V a, const Vec3V min, const Vec3V max) +{ + return BOOL_TO_U32(a.x > max.x || a.y > max.y || a.z > max.z || a.x < min.x || a.y < min.y || a.z < min.z); +} + +PX_FORCE_INLINE PxU32 V3InBounds(const Vec3V a, const Vec3V min, const Vec3V max) +{ + return BOOL_TO_U32(a.x <= max.x && a.y <= max.y && a.z <= max.z && a.x >= min.x && a.y >= min.y && a.z >= min.z); +} + +PX_FORCE_INLINE PxU32 V3OutOfBounds(const Vec3V a, const Vec3V bounds) +{ + return V3OutOfBounds(a, V3Neg(bounds), bounds); +} + +PX_FORCE_INLINE PxU32 V3InBounds(const Vec3V a, const Vec3V bounds) +{ + return V3InBounds(a, V3Neg(bounds), bounds); +} + +PX_FORCE_INLINE void V3Transpose(Vec3V& col0, Vec3V& col1, Vec3V& col2) +{ + const PxF32 t01 = col0.y, t02 = col0.z, t12 = col1.z; + col0.y = col1.x; + col0.z = col2.x; + col1.z = col2.y; + col1.x = t01; + col2.x = t02; + col2.y = t12; +} + +///////////////////////// +// VEC4V +///////////////////////// + +PX_FORCE_INLINE Vec4V V4Splat(const FloatV f) +{ + return Vec4V(f.x, f.x, f.x, f.x); +} + +PX_FORCE_INLINE Vec4V V4Merge(const FloatV* const floatVArray) +{ + return Vec4V(floatVArray[0].x, floatVArray[1].x, floatVArray[2].x, floatVArray[3].x); +} + +PX_FORCE_INLINE Vec4V V4Merge(const FloatVArg x, const FloatVArg y, const FloatVArg z, const FloatVArg w) +{ + return Vec4V(x.x, y.x, z.x, w.x); +} + +PX_FORCE_INLINE Vec4V V4MergeW(const Vec4VArg x, const Vec4VArg y, const Vec4VArg z, const Vec4VArg w) +{ + return Vec4V(x.w, y.w, z.w, w.w); +} + +PX_FORCE_INLINE Vec4V V4MergeZ(const Vec4VArg x, const Vec4VArg y, const Vec4VArg z, const Vec4VArg w) +{ + return Vec4V(x.z, y.z, z.z, w.z); +} + +PX_FORCE_INLINE Vec4V V4MergeY(const Vec4VArg x, const Vec4VArg y, const Vec4VArg z, const Vec4VArg w) +{ + return Vec4V(x.y, y.y, z.y, w.y); +} + +PX_FORCE_INLINE Vec4V V4MergeX(const Vec4VArg x, const Vec4VArg y, const Vec4VArg z, const Vec4VArg w) +{ + return Vec4V(x.x, y.x, z.x, w.x); +} + +PX_FORCE_INLINE Vec4V V4UnpackXY(const Vec4VArg a, const Vec4VArg b) +{ + return Vec4V(a.x, b.x, a.y, b.y); +} + +PX_FORCE_INLINE Vec4V V4UnpackZW(const Vec4VArg a, const Vec4VArg b) +{ + return Vec4V(a.z, b.z, a.w, b.w); +} + +PX_FORCE_INLINE Vec4V V4UnitX() +{ + return Vec4V(1.0f, 0.0f, 0.0f, 0.0f); +} + +PX_FORCE_INLINE Vec4V V4UnitY() +{ + return Vec4V(0.0f, 1.0f, 0.0f, 0.0f); +} + +PX_FORCE_INLINE Vec4V V4UnitZ() +{ + return Vec4V(0.0f, 0.0f, 1.0f, 0.0f); +} + +PX_FORCE_INLINE Vec4V V4UnitW() +{ + return Vec4V(0.0f, 0.0f, 0.0f, 1.0f); +} + +PX_FORCE_INLINE FloatV V4GetX(const Vec4V f) +{ + return FloatV(f.x); +} + +PX_FORCE_INLINE FloatV V4GetY(const Vec4V f) +{ + return FloatV(f.y); +} + +PX_FORCE_INLINE FloatV V4GetZ(const Vec4V f) +{ + return FloatV(f.z); +} + +PX_FORCE_INLINE FloatV V4GetW(const Vec4V f) +{ + return FloatV(f.w); +} + +PX_FORCE_INLINE Vec4V V4SetX(const Vec4V v, const FloatV f) +{ + return Vec4V(f.x, v.y, v.z, v.w); +} + +PX_FORCE_INLINE Vec4V V4SetY(const Vec4V v, const FloatV f) +{ + return Vec4V(v.x, f.x, v.z, v.w); +} + +PX_FORCE_INLINE Vec4V V4SetZ(const Vec4V v, const FloatV f) +{ + return Vec4V(v.x, v.y, f.x, v.w); +} + +PX_FORCE_INLINE Vec4V V4SetW(const Vec4V v, const FloatV f) +{ + return Vec4V(v.x, v.y, v.z, f.x); +} + +PX_FORCE_INLINE Vec4V V4SetW(const Vec3V v, const FloatV f) +{ + return Vec4V(v.x, v.y, v.z, f.x); +} + +PX_FORCE_INLINE Vec4V V4ClearW(const Vec4V v) +{ + return Vec4V(v.x, v.y, v.z, 0.0f); +} + +PX_FORCE_INLINE Vec4V V4PermYXWZ(const Vec4V v) +{ + return Vec4V(v.y, v.x, v.w, v.z); +} + +PX_FORCE_INLINE Vec4V V4PermXZXZ(const Vec4V v) +{ + return Vec4V(v.x, v.z, v.x, v.z); +} + +PX_FORCE_INLINE Vec4V V4PermYWYW(const Vec4V v) +{ + return Vec4V(v.y, v.w, v.y, v.w); +} + +PX_FORCE_INLINE Vec4V V4PermYZXW(const Vec4V v) +{ + return Vec4V(v.y, v.z, v.x, v.w); +} + +PX_FORCE_INLINE Vec4V V4PermZWXY(const Vec4V v) +{ + return Vec4V(v.z, v.w, v.x, v.y); +} + +template +PX_FORCE_INLINE Vec4V V4Perm(const Vec4V v) +{ + const PxF32 f[4] = { v.x, v.y, v.z, v.w }; + return Vec4V(f[_x], f[_y], f[_z], f[_w]); +} + +PX_FORCE_INLINE Vec4V V4Zero() +{ + return V4Load(0.0f); +} + +PX_FORCE_INLINE Vec4V V4One() +{ + return V4Load(1.0f); +} + +PX_FORCE_INLINE Vec4V V4Eps() +{ + return V4Load(PX_EPS_REAL); +} + +PX_FORCE_INLINE Vec4V V4Neg(const Vec4V c) +{ + return Vec4V(-c.x, -c.y, -c.z, -c.w); +} + +PX_FORCE_INLINE Vec4V V4Add(const Vec4V a, const Vec4V b) +{ + return Vec4V(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w); +} + +PX_FORCE_INLINE Vec4V V4Sub(const Vec4V a, const Vec4V b) +{ + return Vec4V(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w); +} + +PX_FORCE_INLINE Vec4V V4Scale(const Vec4V a, const FloatV b) +{ + return Vec4V(a.x * b.x, a.y * b.x, a.z * b.x, a.w * b.x); +} + +PX_FORCE_INLINE Vec4V V4Mul(const Vec4V a, const Vec4V b) +{ + return Vec4V(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w); +} + +PX_FORCE_INLINE Vec4V V4ScaleInv(const Vec4V a, const FloatV b) +{ + const PxF32 bInv = 1.0f / b.x; + return Vec4V(a.x * bInv, a.y * bInv, a.z * bInv, a.w * bInv); +} + +PX_FORCE_INLINE Vec4V V4Div(const Vec4V a, const Vec4V b) +{ + VECMATHAOS_ASSERT(b.x != 0 && b.y != 0 && b.z != 0 && b.w != 0); + return Vec4V(a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w); +} + +PX_FORCE_INLINE Vec4V V4ScaleInvFast(const Vec4V a, const FloatV b) +{ + const PxF32 bInv = 1.0f / b.x; + return Vec4V(a.x * bInv, a.y * bInv, a.z * bInv, a.w * bInv); +} + +PX_FORCE_INLINE Vec4V V4DivFast(const Vec4V a, const Vec4V b) +{ + return Vec4V(a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w); +} + +PX_FORCE_INLINE Vec4V V4Recip(const Vec4V a) +{ + return Vec4V(1.0f / a.x, 1.0f / a.y, 1.0f / a.z, 1.0f / a.w); +} + +PX_FORCE_INLINE Vec4V V4RecipFast(const Vec4V a) +{ + return Vec4V(1.0f / a.x, 1.0f / a.y, 1.0f / a.z, 1.0f / a.w); +} + +PX_FORCE_INLINE Vec4V V4Rsqrt(const Vec4V a) +{ + return Vec4V(PxRecipSqrt(a.x), PxRecipSqrt(a.y), PxRecipSqrt(a.z), PxRecipSqrt(a.w)); +} + +PX_FORCE_INLINE Vec4V V4RsqrtFast(const Vec4V a) +{ + return Vec4V(PxRecipSqrt(a.x), PxRecipSqrt(a.y), PxRecipSqrt(a.z), PxRecipSqrt(a.w)); +} + +PX_FORCE_INLINE Vec4V V4Sqrt(const Vec4V a) +{ + return Vec4V(PxSqrt(a.x), PxSqrt(a.y), PxSqrt(a.z), PxSqrt(a.w)); +} + +PX_FORCE_INLINE Vec4V V4ScaleAdd(const Vec4V a, const FloatV b, const Vec4V c) +{ + return V4Add(V4Scale(a, b), c); +} + +PX_FORCE_INLINE Vec4V V4NegScaleSub(const Vec4V a, const FloatV b, const Vec4V c) +{ + return V4Sub(c, V4Scale(a, b)); +} + +PX_FORCE_INLINE Vec4V V4MulAdd(const Vec4V a, const Vec4V b, const Vec4V c) +{ + return V4Add(V4Mul(a, b), c); +} + +PX_FORCE_INLINE Vec4V V4NegMulSub(const Vec4V a, const Vec4V b, const Vec4V c) +{ + return V4Sub(c, V4Mul(a, b)); +} + +PX_FORCE_INLINE FloatV V4SumElements(const Vec4V a) +{ + return FloatV(a.x + a.y + a.z + a.w); +} + +PX_FORCE_INLINE FloatV V4Dot(const Vec4V a, const Vec4V b) +{ + return FloatV(a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w); +} + +PX_FORCE_INLINE FloatV V4Dot3(const Vec4V a, const Vec4V b) +{ + return FloatV(a.x * b.x + a.y * b.y + a.z * b.z); +} + +PX_FORCE_INLINE Vec4V V4Cross(const Vec4V a, const Vec4V b) +{ + return Vec4V(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x, 0.0f); +} + +PX_FORCE_INLINE FloatV V4Length(const Vec4V a) +{ + return FloatV(PxSqrt(a.x * a.x + a.y * a.y + a.z * a.z + a.w * a.w)); +} + +PX_FORCE_INLINE FloatV V4LengthSq(const Vec4V a) +{ + return V4Dot(a, a); +} + +PX_FORCE_INLINE Vec4V V4Normalize(const Vec4V a) +{ + VECMATHAOS_ASSERT(0 != a.x || 0 != a.y || 0 != a.z || 0 != a.w); + const FloatV length = FloatV(V4Length(a)); + return V4ScaleInv(a, length); +} + +PX_FORCE_INLINE Vec4V V4NormalizeSafe(const Vec4V a, const Vec4V unsafeReturnValue) +{ + const FloatV length = FloatV(V4Length(a)); + if(PX_EPS_REAL >= length.x) + { + return unsafeReturnValue; + } + else + { + return V4ScaleInv(a, length); + } +} +PX_FORCE_INLINE Vec4V V4NormalizeFast(const Vec4V a) +{ + VECMATHAOS_ASSERT(0 != a.x || 0 != a.y || 0 != a.z || 0 != a.w); + const FloatV length = FloatV(V4Length(a)); + return V4ScaleInv(a, length); +} + +PX_FORCE_INLINE Vec4V V4Sel(const BoolV c, const Vec4V a, const Vec4V b) +{ + return Vec4V(c.ux ? a.x : b.x, c.uy ? a.y : b.y, c.uz ? a.z : b.z, c.uw ? a.w : b.w); +} + +PX_FORCE_INLINE BoolV V4IsGrtr(const Vec4V a, const Vec4V b) +{ + return BoolV(BOOL_TO_U32(a.x > b.x), BOOL_TO_U32(a.y > b.y), BOOL_TO_U32(a.z > b.z), BOOL_TO_U32(a.w > b.w)); +} + +PX_FORCE_INLINE BoolV V4IsGrtrOrEq(const Vec4V a, const Vec4V b) +{ + return BoolV(BOOL_TO_U32(a.x >= b.x), BOOL_TO_U32(a.y >= b.y), BOOL_TO_U32(a.z >= b.z), BOOL_TO_U32(a.w >= b.w)); +} + +PX_FORCE_INLINE BoolV V4IsEq(const Vec4V a, const Vec4V b) +{ + return BoolV(BOOL_TO_U32(a.x == b.x), BOOL_TO_U32(a.y == b.y), BOOL_TO_U32(a.z == b.z), BOOL_TO_U32(a.w == b.w)); +} + +PX_FORCE_INLINE Vec4V V4Max(const Vec4V a, const Vec4V b) +{ + return Vec4V(a.x > b.x ? a.x : b.x, a.y > b.y ? a.y : b.y, a.z > b.z ? a.z : b.z, a.w > b.w ? a.w : b.w); +} + +PX_FORCE_INLINE Vec4V V4Min(const Vec4V a, const Vec4V b) +{ + return Vec4V(a.x < b.x ? a.x : b.x, a.y < b.y ? a.y : b.y, a.z < b.z ? a.z : b.z, a.w < b.w ? a.w : b.w); +} + +PX_FORCE_INLINE FloatV V4ExtractMax(const Vec4V a) +{ + const PxF32 t0 = (a.x >= a.y) ? a.x : a.y; + const PxF32 t1 = (a.z >= a.w) ? a.x : a.w; + return t0 >= t1 ? t0 : t1; +} + +PX_FORCE_INLINE FloatV V4ExtractMin(const Vec4V a) +{ + const PxF32 t0 = (a.x <= a.y) ? a.x : a.y; + const PxF32 t1 = (a.z <= a.w) ? a.x : a.w; + return t0 <= t1 ? t0 : t1; +} + +PX_FORCE_INLINE Vec4V V4Clamp(const Vec4V a, const Vec4V minV, const Vec4V maxV) +{ + return V4Max(V4Min(a, maxV), minV); +} + +PX_FORCE_INLINE Vec4V V4Round(const Vec4V a) +{ + return Vec4V(floorf(a.x + 0.5f), floorf(a.y + 0.5f), floorf(a.z + 0.5f), floorf(a.w + 0.5f)); +} + +PX_FORCE_INLINE Vec4V V4Sin(const Vec4V a) +{ + return Vec4V(sinf(a.x), sinf(a.y), sinf(a.z), sinf(a.w)); +} + +PX_FORCE_INLINE Vec4V V4Cos(const Vec4V a) +{ + return Vec4V(cosf(a.x), cosf(a.y), cosf(a.z), cosf(a.w)); +} + +PX_FORCE_INLINE PxU32 V4AllGrtr(const Vec4V a, const Vec4V b) +{ + return BOOL_TO_U32((a.x > b.x) & (a.y > b.y) & (a.z > b.z) & (a.w > b.w)); +} + +PX_FORCE_INLINE PxU32 V4AllGrtrOrEq(const Vec4V a, const Vec4V b) +{ + return BOOL_TO_U32((a.x >= b.x) & (a.y >= b.y) & (a.z >= b.z) & (a.w >= b.w)); +} + +PX_FORCE_INLINE PxU32 V4AllGrtrOrEq3(const Vec4V a, const Vec4V b) +{ + return BOOL_TO_U32((a.x >= b.x) & (a.y >= b.y) & (a.z >= b.z)); +} + +PX_FORCE_INLINE PxU32 V4AllEq(const Vec4V a, const Vec4V b) +{ + return BOOL_TO_U32((a.x == b.x) & (a.y == b.y) & (a.z == b.z) & (a.w == b.w)); +} + +PX_FORCE_INLINE PxU32 V4AnyGrtr3(const Vec4V a, const Vec4V b) +{ + return BOOL_TO_U32((a.x > b.x) | (a.y > b.y) | (a.z > b.z)); +} + +PX_FORCE_INLINE void V4Transpose(Vec4V& col0, Vec4V& col1, Vec4V& col2, Vec4V& col3) +{ + const PxF32 t01 = col0.y, t02 = col0.z, t03 = col0.w; + const PxF32 t12 = col1.z, t13 = col1.w; + const PxF32 t23 = col2.w; + col0.y = col1.x; + col0.z = col2.x; + col0.w = col3.x; + col1.z = col2.y; + col1.w = col3.y; + col2.w = col3.z; + col1.x = t01; + col2.x = t02; + col3.x = t03; + col2.y = t12; + col3.y = t13; + col3.z = t23; +} + +PX_FORCE_INLINE BoolV BFFFF() +{ + return BoolV(FALSE_TO_U32, FALSE_TO_U32, FALSE_TO_U32, FALSE_TO_U32); +} +PX_FORCE_INLINE BoolV BFFFT() +{ + return BoolV(FALSE_TO_U32, FALSE_TO_U32, FALSE_TO_U32, TRUE_TO_U32); +} +PX_FORCE_INLINE BoolV BFFTF() +{ + return BoolV(FALSE_TO_U32, FALSE_TO_U32, TRUE_TO_U32, FALSE_TO_U32); +} +PX_FORCE_INLINE BoolV BFFTT() +{ + return BoolV(FALSE_TO_U32, FALSE_TO_U32, TRUE_TO_U32, TRUE_TO_U32); +} +PX_FORCE_INLINE BoolV BFTFF() +{ + return BoolV(FALSE_TO_U32, TRUE_TO_U32, FALSE_TO_U32, FALSE_TO_U32); +} +PX_FORCE_INLINE BoolV BFTFT() +{ + return BoolV(FALSE_TO_U32, TRUE_TO_U32, FALSE_TO_U32, TRUE_TO_U32); +} +PX_FORCE_INLINE BoolV BFTTF() +{ + return BoolV(FALSE_TO_U32, TRUE_TO_U32, TRUE_TO_U32, FALSE_TO_U32); +} +PX_FORCE_INLINE BoolV BFTTT() +{ + return BoolV(FALSE_TO_U32, TRUE_TO_U32, TRUE_TO_U32, TRUE_TO_U32); +} +PX_FORCE_INLINE BoolV BTFFF() +{ + return BoolV(TRUE_TO_U32, FALSE_TO_U32, FALSE_TO_U32, FALSE_TO_U32); +} +PX_FORCE_INLINE BoolV BTFFT() +{ + return BoolV(TRUE_TO_U32, FALSE_TO_U32, FALSE_TO_U32, TRUE_TO_U32); +} +PX_FORCE_INLINE BoolV BTFTF() +{ + return BoolV(TRUE_TO_U32, FALSE_TO_U32, TRUE_TO_U32, FALSE_TO_U32); +} +PX_FORCE_INLINE BoolV BTFTT() +{ + return BoolV(TRUE_TO_U32, FALSE_TO_U32, TRUE_TO_U32, TRUE_TO_U32); +} +PX_FORCE_INLINE BoolV BTTFF() +{ + return BoolV(TRUE_TO_U32, TRUE_TO_U32, FALSE_TO_U32, FALSE_TO_U32); +} +PX_FORCE_INLINE BoolV BTTFT() +{ + return BoolV(TRUE_TO_U32, TRUE_TO_U32, FALSE_TO_U32, TRUE_TO_U32); +} +PX_FORCE_INLINE BoolV BTTTF() +{ + return BoolV(TRUE_TO_U32, TRUE_TO_U32, TRUE_TO_U32, FALSE_TO_U32); +} +PX_FORCE_INLINE BoolV BTTTT() +{ + return BoolV(TRUE_TO_U32, TRUE_TO_U32, TRUE_TO_U32, TRUE_TO_U32); +} + +PX_FORCE_INLINE BoolV BXMask() +{ + return BTFFF(); +} +PX_FORCE_INLINE BoolV BYMask() +{ + return BFTFF(); +} +PX_FORCE_INLINE BoolV BZMask() +{ + return BFFTF(); +} +PX_FORCE_INLINE BoolV BWMask() +{ + return BFFFT(); +} + +PX_FORCE_INLINE BoolV BGetX(const BoolV a) +{ + return BoolV(a.ux, a.ux, a.ux, a.ux); +} + +PX_FORCE_INLINE BoolV BGetY(const BoolV a) +{ + return BoolV(a.uy, a.uy, a.uy, a.uy); +} + +PX_FORCE_INLINE BoolV BGetZ(const BoolV a) +{ + return BoolV(a.uz, a.uz, a.uz, a.uz); +} + +PX_FORCE_INLINE BoolV BGetW(const BoolV a) +{ + return BoolV(a.uw, a.uw, a.uw, a.uw); +} + +PX_FORCE_INLINE BoolV BSetX(const BoolV v, const BoolV f) +{ + return BoolV(f.ux, v.uy, v.uz, v.uw); +} + +PX_FORCE_INLINE BoolV BSetY(const BoolV v, const BoolV f) +{ + return BoolV(v.ux, f.uy, v.uz, v.uw); +} + +PX_FORCE_INLINE BoolV BSetZ(const BoolV v, const BoolV f) +{ + return BoolV(v.ux, v.uy, f.uz, v.uw); +} + +PX_FORCE_INLINE BoolV BSetW(const BoolV v, const BoolV f) +{ + return BoolV(v.ux, v.uy, v.uz, f.uw); +} + +template +BoolV BSplatElement(BoolV a) +{ + PxU32* b = (PxU32*)&a; + return BoolV(b[index], b[index], b[index], b[index]); +} + +PX_FORCE_INLINE BoolV BAnd(const BoolV a, const BoolV b) +{ + return BoolV(BOOL_TO_U32(a.ux && b.ux), BOOL_TO_U32(a.uy && b.uy), BOOL_TO_U32(a.uz && b.uz), BOOL_TO_U32(a.uw && b.uw)); +} + +PX_FORCE_INLINE BoolV BAndNot(const BoolV a, const BoolV b) +{ + return BoolV(a.ux & ~b.ux, a.uy & ~b.uy, a.uz & ~b.uz, a.uw & ~b.uw); +} + +PX_FORCE_INLINE BoolV BNot(const BoolV a) +{ + return BoolV(~a.ux, ~a.uy, ~a.uz, ~a.uw); +} + +PX_FORCE_INLINE BoolV BOr(const BoolV a, const BoolV b) +{ + return BoolV(BOOL_TO_U32(a.ux || b.ux), BOOL_TO_U32(a.uy || b.uy), BOOL_TO_U32(a.uz || b.uz), BOOL_TO_U32(a.uw || b.uw)); +} + +PX_FORCE_INLINE PxU32 BAllEq(const BoolV a, const BoolV b) +{ + return (a.ux == b.ux && a.uy == b.uy && a.uz == b.uz && a.uw == b.uw ? 1 : 0); +} + +PX_FORCE_INLINE PxU32 BAllEqTTTT(const BoolV a) +{ + return BAllEq(a, BTTTT()); +} + +PX_FORCE_INLINE PxU32 BAllEqFFFF(const BoolV a) +{ + return BAllEq(a, BFFFF()); +} + +PX_FORCE_INLINE BoolV BAllTrue4(const BoolV a) +{ + return (a.ux & a.uy & a.uz & a.uw) ? BTTTT() : BFFFF(); +} + +PX_FORCE_INLINE BoolV BAnyTrue4(const BoolV a) +{ + return (a.ux | a.uy | a.uz | a.uw) ? BTTTT() : BFFFF(); +} + +PX_FORCE_INLINE BoolV BAllTrue3(const BoolV a) +{ + return (a.ux & a.uy & a.uz) ? BTTTT() : BFFFF(); +} + +PX_FORCE_INLINE BoolV BAnyTrue3(const BoolV a) +{ + return (a.ux | a.uy | a.uz) ? BTTTT() : BFFFF(); +} + +PX_FORCE_INLINE PxU32 BGetBitMask(const BoolV a) +{ + return (a.ux & 1) | (a.uy & 2) | (a.uz & 4) | (a.uw & 8); +} + +////////////////////////////////// +// MAT33V +////////////////////////////////// + +PX_FORCE_INLINE Vec3V M33MulV3(const Mat33V& a, const Vec3V b) +{ + return Vec3V(a.col0.x * b.x + a.col1.x * b.y + a.col2.x * b.z, a.col0.y * b.x + a.col1.y * b.y + a.col2.y * b.z, + a.col0.z * b.x + a.col1.z * b.y + a.col2.z * b.z); +} + +PX_FORCE_INLINE Vec3V M33TrnspsMulV3(const Mat33V& a, const Vec3V b) +{ + return Vec3V(a.col0.x * b.x + a.col0.y * b.y + a.col0.z * b.z, a.col1.x * b.x + a.col1.y * b.y + a.col1.z * b.z, + a.col2.x * b.x + a.col2.y * b.y + a.col2.z * b.z); +} + +PX_FORCE_INLINE Vec3V M33MulV3AddV3(const Mat33V& A, const Vec3V b, const Vec3V c) +{ + const FloatV x = V3GetX(b); + const FloatV y = V3GetY(b); + const FloatV z = V3GetZ(b); + Vec3V result = V3ScaleAdd(A.col0, x, c); + result = V3ScaleAdd(A.col1, y, result); + return V3ScaleAdd(A.col2, z, result); +} + +PX_FORCE_INLINE Mat33V M33MulM33(const Mat33V& a, const Mat33V& b) +{ + return Mat33V(M33MulV3(a, b.col0), M33MulV3(a, b.col1), M33MulV3(a, b.col2)); +} + +PX_FORCE_INLINE Mat33V M33Add(const Mat33V& a, const Mat33V& b) +{ + return Mat33V(V3Add(a.col0, b.col0), V3Add(a.col1, b.col1), V3Add(a.col2, b.col2)); +} + +PX_FORCE_INLINE Mat33V M33Scale(const Mat33V& a, const FloatV& b) +{ + return Mat33V(V3Scale(a.col0, b), V3Scale(a.col1, b), V3Scale(a.col2, b)); +} + +PX_FORCE_INLINE Mat33V M33Sub(const Mat33V& a, const Mat33V& b) +{ + return Mat33V(V3Sub(a.col0, b.col0), V3Sub(a.col1, b.col1), V3Sub(a.col2, b.col2)); +} + +PX_FORCE_INLINE Mat33V M33Neg(const Mat33V& a) +{ + return Mat33V(V3Neg(a.col0), V3Neg(a.col1), V3Neg(a.col2)); +} + +PX_FORCE_INLINE Mat33V M33Abs(const Mat33V& a) +{ + return Mat33V(V3Abs(a.col0), V3Abs(a.col1), V3Abs(a.col2)); +} + +PX_FORCE_INLINE Mat33V M33Diagonal(const Vec3VArg d) +{ + const Vec3V x = V3Mul(V3UnitX(), d); + const Vec3V y = V3Mul(V3UnitY(), d); + const Vec3V z = V3Mul(V3UnitZ(), d); + return Mat33V(x, y, z); +} + +PX_FORCE_INLINE Mat33V M33Inverse(const Mat33V& a) +{ + const PxF32 det = a.col0.x * (a.col1.y * a.col2.z - a.col1.z * a.col2.y) - + a.col1.x * (a.col0.y * a.col2.z - a.col2.y * a.col0.z) + + a.col2.x * (a.col0.y * a.col1.z - a.col1.y * a.col0.z); + + const PxF32 invDet = 1.0f / det; + + Mat33V ret; + ret.col0.x = invDet * (a.col1.y * a.col2.z - a.col2.y * a.col1.z); + ret.col0.y = invDet * (a.col2.y * a.col0.z - a.col0.y * a.col2.z); + ret.col0.z = invDet * (a.col0.y * a.col1.z - a.col1.y * a.col0.z); + + ret.col1.x = invDet * (a.col2.x * a.col1.z - a.col1.x * a.col2.z); + ret.col1.y = invDet * (a.col0.x * a.col2.z - a.col2.x * a.col0.z); + ret.col1.z = invDet * (a.col1.x * a.col0.z - a.col0.x * a.col1.z); + + ret.col2.x = invDet * (a.col1.x * a.col2.y - a.col2.x * a.col1.y); + ret.col2.y = invDet * (a.col2.x * a.col0.y - a.col0.x * a.col2.y); + ret.col2.z = invDet * (a.col0.x * a.col1.y - a.col1.x * a.col0.y); + + return ret; +} + +PX_FORCE_INLINE Mat33V Mat33V_From_PxMat33(const PxMat33& m) +{ + return Mat33V(V3LoadU(m.column0), V3LoadU(m.column1), V3LoadU(m.column2)); +} + +PX_FORCE_INLINE void PxMat33_From_Mat33V(const Mat33V& m, PxMat33& out) +{ + PX_ASSERT((size_t(&out) & 15) == 0); + V3StoreU(m.col0, out.column0); + V3StoreU(m.col1, out.column1); + V3StoreU(m.col2, out.column2); +} + +PX_FORCE_INLINE Mat33V M33Trnsps(const Mat33V& a) +{ + return Mat33V(Vec3V(a.col0.x, a.col1.x, a.col2.x), Vec3V(a.col0.y, a.col1.y, a.col2.y), + Vec3V(a.col0.z, a.col1.z, a.col2.z)); +} + +PX_FORCE_INLINE Mat33V M33Identity() +{ + return Mat33V(V3UnitX(), V3UnitY(), V3UnitZ()); +} + +////////////////////////////////// +// MAT34V +////////////////////////////////// + +PX_FORCE_INLINE Vec3V M34MulV3(const Mat34V& a, const Vec3V b) +{ + return Vec3V(a.col0.x * b.x + a.col1.x * b.y + a.col2.x * b.z + a.col3.x, + a.col0.y * b.x + a.col1.y * b.y + a.col2.y * b.z + a.col3.y, + a.col0.z * b.x + a.col1.z * b.y + a.col2.z * b.z + a.col3.z); +} + +PX_FORCE_INLINE Vec3V M34Mul33V3(const Mat34V& a, const Vec3V b) +{ + return Vec3V(a.col0.x * b.x + a.col1.x * b.y + a.col2.x * b.z, a.col0.y * b.x + a.col1.y * b.y + a.col2.y * b.z, + a.col0.z * b.x + a.col1.z * b.y + a.col2.z * b.z); +} + +PX_FORCE_INLINE Vec3V M34TrnspsMul33V3(const Mat34V& a, const Vec3V b) +{ + return Vec3V(a.col0.x * b.x + a.col0.y * b.y + a.col0.z * b.z, a.col1.x * b.x + a.col1.y * b.y + a.col1.z * b.z, + a.col2.x * b.x + a.col2.y * b.y + a.col2.z * b.z); +} + +PX_FORCE_INLINE Mat34V M34MulM34(const Mat34V& a, const Mat34V& b) +{ + return Mat34V(M34Mul33V3(a, b.col0), M34Mul33V3(a, b.col1), M34Mul33V3(a, b.col2), M34MulV3(a, b.col3)); +} + +PX_FORCE_INLINE Mat33V M34MulM33(const Mat34V& a, const Mat33V& b) +{ + return Mat33V(M34Mul33V3(a, b.col0), M34Mul33V3(a, b.col1), M34Mul33V3(a, b.col2)); +} + +PX_FORCE_INLINE Mat33V M34Mul33V3(const Mat34V& a, const Mat33V& b) +{ + return Mat33V(M34Mul33V3(a, b.col0), M34Mul33V3(a, b.col1), M34Mul33V3(a, b.col2)); +} + +PX_FORCE_INLINE Mat33V M34Mul33MM34(const Mat34V& a, const Mat34V& b) +{ + return Mat33V(M34Mul33V3(a, b.col0), M34Mul33V3(a, b.col1), M34Mul33V3(a, b.col2)); +} + +PX_FORCE_INLINE Mat34V M34Add(const Mat34V& a, const Mat34V& b) +{ + return Mat34V(V3Add(a.col0, b.col0), V3Add(a.col1, b.col1), V3Add(a.col2, b.col2), V3Add(a.col3, b.col3)); +} + +PX_FORCE_INLINE Mat33V M34Trnsps33(const Mat34V& a) +{ + return Mat33V(Vec3V(a.col0.x, a.col1.x, a.col2.x), Vec3V(a.col0.y, a.col1.y, a.col2.y), + Vec3V(a.col0.z, a.col1.z, a.col2.z)); +} + +////////////////////////////////// +// MAT44V +////////////////////////////////// + +PX_FORCE_INLINE Vec4V M44MulV4(const Mat44V& a, const Vec4V b) +{ + return Vec4V(a.col0.x * b.x + a.col1.x * b.y + a.col2.x * b.z + a.col3.x * b.w, + a.col0.y * b.x + a.col1.y * b.y + a.col2.y * b.z + a.col3.y * b.w, + a.col0.z * b.x + a.col1.z * b.y + a.col2.z * b.z + a.col3.z * b.w, + a.col0.w * b.x + a.col1.w * b.y + a.col2.w * b.z + a.col3.w * b.w); +} + +PX_FORCE_INLINE Vec4V M44TrnspsMulV4(const Mat44V& a, const Vec4V b) +{ + return Vec4V(a.col0.x * b.x + a.col0.y * b.y + a.col0.z * b.z + a.col0.w * b.w, + a.col1.x * b.x + a.col1.y * b.y + a.col1.z * b.z + a.col1.w * b.w, + a.col2.x * b.x + a.col2.y * b.y + a.col2.z * b.z + a.col2.w * b.w, + a.col3.x * b.x + a.col3.y * b.y + a.col3.z * b.z + a.col3.w * b.w); +} + +PX_FORCE_INLINE Mat44V M44MulM44(const Mat44V& a, const Mat44V& b) +{ + return Mat44V(M44MulV4(a, b.col0), M44MulV4(a, b.col1), M44MulV4(a, b.col2), M44MulV4(a, b.col3)); +} + +PX_FORCE_INLINE Mat44V M44Add(const Mat44V& a, const Mat44V& b) +{ + return Mat44V(V4Add(a.col0, b.col0), V4Add(a.col1, b.col1), V4Add(a.col2, b.col2), V4Add(a.col3, b.col3)); +} + +PX_FORCE_INLINE Mat44V M44Inverse(const Mat44V& a) +{ + PxF32 tmp[12]; + PxF32 dst[16]; + PxF32 det; + + const PxF32 src[16] = { a.col0.x, a.col0.y, a.col0.z, a.col0.w, a.col1.x, a.col1.y, a.col1.z, a.col1.w, + a.col2.x, a.col2.y, a.col2.z, a.col2.w, a.col3.x, a.col3.y, a.col3.z, a.col3.w }; + + tmp[0] = src[10] * src[15]; + tmp[1] = src[11] * src[14]; + tmp[2] = src[9] * src[15]; + tmp[3] = src[11] * src[13]; + tmp[4] = src[9] * src[14]; + tmp[5] = src[10] * src[13]; + tmp[6] = src[8] * src[15]; + tmp[7] = src[11] * src[12]; + tmp[8] = src[8] * src[14]; + tmp[9] = src[10] * src[12]; + tmp[10] = src[8] * src[13]; + tmp[11] = src[9] * src[12]; + + dst[0] = tmp[0] * src[5] + tmp[3] * src[6] + tmp[4] * src[7]; + dst[0] -= tmp[1] * src[5] + tmp[2] * src[6] + tmp[5] * src[7]; + dst[1] = tmp[1] * src[4] + tmp[6] * src[6] + tmp[9] * src[7]; + dst[1] -= tmp[0] * src[4] + tmp[7] * src[6] + tmp[8] * src[7]; + dst[2] = tmp[2] * src[4] + tmp[7] * src[5] + tmp[10] * src[7]; + dst[2] -= tmp[3] * src[4] + tmp[6] * src[5] + tmp[11] * src[7]; + dst[3] = tmp[5] * src[4] + tmp[8] * src[5] + tmp[11] * src[6]; + dst[3] -= tmp[4] * src[4] + tmp[9] * src[5] + tmp[10] * src[6]; + dst[4] = tmp[1] * src[1] + tmp[2] * src[2] + tmp[5] * src[3]; + dst[4] -= tmp[0] * src[1] + tmp[3] * src[2] + tmp[4] * src[3]; + dst[5] = tmp[0] * src[0] + tmp[7] * src[2] + tmp[8] * src[3]; + dst[5] -= tmp[1] * src[0] + tmp[6] * src[2] + tmp[9] * src[3]; + dst[6] = tmp[3] * src[0] + tmp[6] * src[1] + tmp[11] * src[3]; + dst[6] -= tmp[2] * src[0] + tmp[7] * src[1] + tmp[10] * src[3]; + dst[7] = tmp[4] * src[0] + tmp[9] * src[1] + tmp[10] * src[2]; + dst[7] -= tmp[5] * src[0] + tmp[8] * src[1] + tmp[11] * src[2]; + + tmp[0] = src[2] * src[7]; + tmp[1] = src[3] * src[6]; + tmp[2] = src[1] * src[7]; + tmp[3] = src[3] * src[5]; + tmp[4] = src[1] * src[6]; + tmp[5] = src[2] * src[5]; + tmp[6] = src[0] * src[7]; + tmp[7] = src[3] * src[4]; + tmp[8] = src[0] * src[6]; + tmp[9] = src[2] * src[4]; + tmp[10] = src[0] * src[5]; + tmp[11] = src[1] * src[4]; + + dst[8] = tmp[0] * src[13] + tmp[3] * src[14] + tmp[4] * src[15]; + dst[8] -= tmp[1] * src[13] + tmp[2] * src[14] + tmp[5] * src[15]; + dst[9] = tmp[1] * src[12] + tmp[6] * src[14] + tmp[9] * src[15]; + dst[9] -= tmp[0] * src[12] + tmp[7] * src[14] + tmp[8] * src[15]; + dst[10] = tmp[2] * src[12] + tmp[7] * src[13] + tmp[10] * src[15]; + dst[10] -= tmp[3] * src[12] + tmp[6] * src[13] + tmp[11] * src[15]; + dst[11] = tmp[5] * src[12] + tmp[8] * src[13] + tmp[11] * src[14]; + dst[11] -= tmp[4] * src[12] + tmp[9] * src[13] + tmp[10] * src[14]; + dst[12] = tmp[2] * src[10] + tmp[5] * src[11] + tmp[1] * src[9]; + dst[12] -= tmp[4] * src[11] + tmp[0] * src[9] + tmp[3] * src[10]; + dst[13] = tmp[8] * src[11] + tmp[0] * src[8] + tmp[7] * src[10]; + dst[13] -= tmp[6] * src[10] + tmp[9] * src[11] + tmp[1] * src[8]; + dst[14] = tmp[6] * src[9] + tmp[11] * src[11] + tmp[3] * src[8]; + dst[14] -= tmp[10] * src[11] + tmp[2] * src[8] + tmp[7] * src[9]; + dst[15] = tmp[10] * src[10] + tmp[4] * src[8] + tmp[9] * src[9]; + dst[15] -= tmp[8] * src[9] + tmp[11] * src[10] + tmp[5] * src[8]; + + det = src[0] * dst[0] + src[1] * dst[1] + src[2] * dst[2] + src[3] * dst[3]; + + det = 1.0f / det; + for(PxU32 j = 0; j < 16; j++) + { + dst[j] *= det; + } + + return Mat44V(Vec4V(dst[0], dst[4], dst[8], dst[12]), Vec4V(dst[1], dst[5], dst[9], dst[13]), + Vec4V(dst[2], dst[6], dst[10], dst[14]), Vec4V(dst[3], dst[7], dst[11], dst[15])); +} + +PX_FORCE_INLINE Mat44V M44Trnsps(const Mat44V& a) +{ + return Mat44V(Vec4V(a.col0.x, a.col1.x, a.col2.x, a.col3.x), Vec4V(a.col0.y, a.col1.y, a.col2.y, a.col3.y), + Vec4V(a.col0.z, a.col1.z, a.col2.z, a.col3.z), Vec4V(a.col0.w, a.col1.w, a.col2.w, a.col3.w)); +} + +PX_FORCE_INLINE Vec4V V4LoadXYZW(const PxF32& x, const PxF32& y, const PxF32& z, const PxF32& w) +{ + return Vec4V(x, y, z, w); +} + +/* +PX_FORCE_INLINE VecU16V V4U32PK(VecU32V a, VecU32V b) +{ + return VecU16V( + PxU16(PxClamp((a).u32[0], 0, 0xFFFF)), + PxU16(PxClamp((a).u32[1], 0, 0xFFFF)), + PxU16(PxClamp((a).u32[2], 0, 0xFFFF)), + PxU16(PxClamp((a).u32[3], 0, 0xFFFF)), + PxU16(PxClamp((b).u32[0], 0, 0xFFFF)), + PxU16(PxClamp((b).u32[1], 0, 0xFFFF)), + PxU16(PxClamp((b).u32[2], 0, 0xFFFF)), + PxU16(PxClamp((b).u32[3], 0, 0xFFFF))); +} +*/ + +PX_FORCE_INLINE VecU32V V4U32Sel(const BoolV c, const VecU32V a, const VecU32V b) +{ + return VecU32V(c.ux ? a.u32[0] : b.u32[0], c.uy ? a.u32[1] : b.u32[1], c.uz ? a.u32[2] : b.u32[2], + c.uw ? a.u32[3] : b.u32[3]); +} + +PX_FORCE_INLINE VecU32V V4U32or(VecU32V a, VecU32V b) +{ + return VecU32V((a).u32[0] | (b).u32[0], (a).u32[1] | (b).u32[1], (a).u32[2] | (b).u32[2], (a).u32[3] | (b).u32[3]); +} + +PX_FORCE_INLINE VecU32V V4U32xor(VecU32V a, VecU32V b) +{ + return VecU32V((a).u32[0] ^ (b).u32[0], (a).u32[1] ^ (b).u32[1], (a).u32[2] ^ (b).u32[2], (a).u32[3] ^ (b).u32[3]); +} + +PX_FORCE_INLINE VecU32V V4U32and(VecU32V a, VecU32V b) +{ + return VecU32V((a).u32[0] & (b).u32[0], (a).u32[1] & (b).u32[1], (a).u32[2] & (b).u32[2], (a).u32[3] & (b).u32[3]); +} + +PX_FORCE_INLINE VecU32V V4U32Andc(VecU32V a, VecU32V b) +{ + return VecU32V((a).u32[0] & ~(b).u32[0], (a).u32[1] & ~(b).u32[1], (a).u32[2] & ~(b).u32[2], + (a).u32[3] & ~(b).u32[3]); +} + +/* +PX_FORCE_INLINE VecU16V V4U16Or(VecU16V a, VecU16V b) +{ + return VecU16V( + (a).u16[0]|(b).u16[0], (a).u16[1]|(b).u16[1], (a).u16[2]|(b).u16[2], (a).u16[3]|(b).u16[3], + (a).u16[4]|(b).u16[4], (a).u16[5]|(b).u16[5], (a).u16[6]|(b).u16[6], (a).u16[7]|(b).u16[7]); +} +*/ + +/* +PX_FORCE_INLINE VecU16V V4U16And(VecU16V a, VecU16V b) +{ + return VecU16V( + (a).u16[0]&(b).u16[0], (a).u16[1]&(b).u16[1], (a).u16[2]&(b).u16[2], (a).u16[3]&(b).u16[3], + (a).u16[4]&(b).u16[4], (a).u16[5]&(b).u16[5], (a).u16[6]&(b).u16[6], (a).u16[7]&(b).u16[7]); +} +*/ + +/* +PX_FORCE_INLINE VecU16V V4U16Andc(VecU16V a, VecU16V b) +{ + return VecU16V( + (a).u16[0]&~(b).u16[0], (a).u16[1]&~(b).u16[1], (a).u16[2]&~(b).u16[2], (a).u16[3]&~(b).u16[3], + (a).u16[4]&~(b).u16[4], (a).u16[5]&~(b).u16[5], (a).u16[6]&~(b).u16[6], (a).u16[7]&~(b).u16[7]); +} +*/ + +/* +template PX_FORCE_INLINE VecI32V V4ISplat() +{ + return VecI32V(a, a, a, a); +} + +template PX_FORCE_INLINE VecU32V V4USplat() +{ + return VecU32V(a, a, a, a); +} +*/ + +/* +PX_FORCE_INLINE void V4U16StoreAligned(VecU16V val, VecU16V* address) +{ + *address = val; +} +*/ + +PX_FORCE_INLINE void V4U32StoreAligned(VecU32V val, VecU32V* address) +{ + *address = val; +} + +PX_FORCE_INLINE Vec4V V4Andc(const Vec4V a, const VecU32V b) +{ + VecU32V r = V4U32Andc(*reinterpret_cast(&a), b); + return (*reinterpret_cast(&r)); +} + +PX_FORCE_INLINE VecU32V V4IsGrtrV32u(const Vec4V a, const Vec4V b) +{ + return VecU32V(a.x > b.x ? 0xFFFFffff : 0, a.y > b.y ? 0xFFFFffff : 0, a.z > b.z ? 0xFFFFffff : 0, + a.w > b.w ? 0xFFFFffff : 0); +} + +PX_FORCE_INLINE VecU16V V4U16LoadAligned(VecU16V* addr) +{ + return *addr; +} + +PX_FORCE_INLINE VecU16V V4U16LoadUnaligned(VecU16V* addr) +{ + return *addr; +} + +PX_FORCE_INLINE VecU16V V4U16CompareGt(VecU16V a, VecU16V b) +{ + return VecU16V + ( + BOOL_TO_U16(a.u16[0] > b.u16[0]), BOOL_TO_U16(a.u16[1] > b.u16[1]), BOOL_TO_U16(a.u16[2] > b.u16[2]), BOOL_TO_U16(a.u16[3] > b.u16[3]), + BOOL_TO_U16(a.u16[4] > b.u16[4]), BOOL_TO_U16(a.u16[5] > b.u16[5]), BOOL_TO_U16(a.u16[6] > b.u16[6]), BOOL_TO_U16(a.u16[7] > b.u16[7]) + ); +} + +PX_FORCE_INLINE VecU16V V4I16CompareGt(VecU16V a, VecU16V b) +{ + return VecU16V + ( + BOOL_TO_U16(a.i16[0] > b.i16[0]), BOOL_TO_U16(a.i16[1] > b.i16[1]), BOOL_TO_U16(a.i16[2] > b.i16[2]), BOOL_TO_U16(a.i16[3] > b.i16[3]), + BOOL_TO_U16(a.i16[4] > b.i16[4]), BOOL_TO_U16(a.i16[5] > b.i16[5]), BOOL_TO_U16(a.i16[6] > b.i16[6]), BOOL_TO_U16(a.i16[7] > b.i16[7]) + ); +} + +PX_FORCE_INLINE Vec4V Vec4V_From_VecU32V(VecU32V a) +{ + return Vec4V(PxF32((a).u32[0]), PxF32((a).u32[1]), PxF32((a).u32[2]), PxF32((a).u32[3])); +} + +PX_FORCE_INLINE Vec4V Vec4V_From_VecI32V(VecI32V a) +{ + return Vec4V(PxF32((a).i32[0]), PxF32((a).i32[1]), PxF32((a).i32[2]), PxF32((a).i32[3])); +} + +PX_FORCE_INLINE VecI32V VecI32V_From_Vec4V(Vec4V a) +{ + float* data = (float*)&a; + return VecI32V(PxI32(data[0]), PxI32(data[1]), PxI32(data[2]), PxI32(data[3])); +} + +PX_FORCE_INLINE Vec4V Vec4V_ReinterpretFrom_VecU32V(VecU32V a) +{ + Vec4V b = *reinterpret_cast(&a); + return b; +} + +PX_FORCE_INLINE Vec4V Vec4V_ReinterpretFrom_VecI32V(VecI32V a) +{ + Vec4V b = *reinterpret_cast(&a); + return b; +} + +PX_FORCE_INLINE VecU32V VecU32V_ReinterpretFrom_Vec4V(Vec4V a) +{ + VecU32V b = *reinterpret_cast(&a); + return b; +} + +PX_FORCE_INLINE VecI32V VecI32V_ReinterpretFrom_Vec4V(Vec4V a) +{ + VecI32V b = *reinterpret_cast(&a); + return b; +} + +template +PX_FORCE_INLINE VecU32V V4U32SplatElement(VecU32V a) +{ + return VecU32V((a).u32[index], (a).u32[index], (a).u32[index], (a).u32[index]); +} + +template +PX_FORCE_INLINE VecU32V V4U32SplatElement(BoolV a) +{ + const PxU32 u = (&a.ux)[index]; + return VecU32V(u, u, u, u); +} + +template +PX_FORCE_INLINE Vec4V V4SplatElement(Vec4V a) +{ + float* data = (float*)&a; + return Vec4V(data[index], data[index], data[index], data[index]); +} + +PX_FORCE_INLINE VecU32V U4LoadXYZW(PxU32 x, PxU32 y, PxU32 z, PxU32 w) +{ + return VecU32V(x, y, z, w); +} + +PX_FORCE_INLINE Vec4V V4Abs(const Vec4V a) +{ + return V4Max(a, V4Neg(a)); +} + +PX_FORCE_INLINE BoolV V4IsEqU32(const VecU32V a, const VecU32V b) +{ + return BoolV(BOOL_TO_U32(a.u32[0] == b.u32[0]), BOOL_TO_U32(a.u32[1] == b.u32[1]), BOOL_TO_U32(a.u32[2] == b.u32[2]), BOOL_TO_U32(a.u32[3] == b.u32[3])); +} + +PX_FORCE_INLINE VecU32V U4Load(const PxU32 i) +{ + return VecU32V(i, i, i, i); +} + +PX_FORCE_INLINE VecU32V U4LoadU(const PxU32* i) +{ + return VecU32V(i[0], i[1], i[2], i[3]); +} + +PX_FORCE_INLINE VecU32V U4LoadA(const PxU32* i) +{ + return VecU32V(i[0], i[1], i[2], i[3]); +} + +PX_FORCE_INLINE VecI32V I4Load(const PxI32 i) +{ + return VecI32V(i, i, i, i); +} + +PX_FORCE_INLINE VecI32V I4LoadU(const PxI32* i) +{ + return VecI32V(i[0], i[1], i[2], i[3]); +} + +PX_FORCE_INLINE VecI32V I4LoadA(const PxI32* i) +{ + return VecI32V(i[0], i[1], i[2], i[3]); +} + +PX_FORCE_INLINE VecI32V VecI32V_Add(const VecI32VArg a, const VecI32VArg b) +{ + return VecI32V(a.i32[0] + b.i32[0], a.i32[1] + b.i32[1], a.i32[2] + b.i32[2], a.i32[3] + b.i32[3]); +} + +PX_FORCE_INLINE VecI32V VecI32V_Sub(const VecI32VArg a, const VecI32VArg b) +{ + return VecI32V(a.i32[0] - b.i32[0], a.i32[1] - b.i32[1], a.i32[2] - b.i32[2], a.i32[3] - b.i32[3]); +} + +PX_FORCE_INLINE BoolV VecI32V_IsGrtr(const VecI32VArg a, const VecI32VArg b) +{ + return BoolV(BOOL_TO_U32(a.i32[0] > b.i32[0]), BOOL_TO_U32(a.i32[1] > b.i32[1]), BOOL_TO_U32(a.i32[2] > b.i32[2]), BOOL_TO_U32(a.i32[3] > b.i32[3])); +} + +PX_FORCE_INLINE BoolV VecI32V_IsEq(const VecI32VArg a, const VecI32VArg b) +{ + return BoolV(BOOL_TO_U32(a.i32[0] == b.i32[0]), BOOL_TO_U32(a.i32[1] == b.i32[1]), BOOL_TO_U32(a.i32[2] == b.i32[2]), BOOL_TO_U32(a.i32[3] == b.i32[3])); +} + +PX_FORCE_INLINE VecI32V V4I32Sel(const BoolV c, const VecI32V a, const VecI32V b) +{ + return VecI32V(c.ux ? a.i32[0] : b.i32[0], c.uy ? a.i32[1] : b.i32[1], c.uz ? a.i32[2] : b.i32[2], + c.uw ? a.i32[3] : b.i32[3]); +} + +PX_FORCE_INLINE VecI32V VecI32V_Zero() +{ + return VecI32V(0, 0, 0, 0); +} + +PX_FORCE_INLINE VecI32V VecI32V_One() +{ + return VecI32V(1, 1, 1, 1); +} + +PX_FORCE_INLINE VecI32V VecI32V_Two() +{ + return VecI32V(2, 2, 2, 2); +} + +PX_FORCE_INLINE VecI32V VecI32V_MinusOne() +{ + return VecI32V(-1, -1, -1, -1); +} + +PX_FORCE_INLINE VecU32V U4Zero() +{ + return VecU32V(0, 0, 0, 0); +} + +PX_FORCE_INLINE VecU32V U4One() +{ + return VecU32V(1, 1, 1, 1); +} + +PX_FORCE_INLINE VecU32V U4Two() +{ + return VecU32V(2, 2, 2, 2); +} + +PX_FORCE_INLINE VecShiftV VecI32V_PrepareShift(const VecI32VArg shift) +{ + return shift; +} + +PX_FORCE_INLINE VecI32V VecI32V_LeftShift(const VecI32VArg a, const VecShiftVArg count) +{ + return VecI32V(a.i32[0] << count.i32[0], a.i32[1] << count.i32[1], a.i32[2] << count.i32[2], a.i32[3] + << count.i32[3]); +} + +PX_FORCE_INLINE VecI32V VecI32V_RightShift(const VecI32VArg a, const VecShiftVArg count) +{ + return VecI32V(a.i32[0] >> count.i32[0], a.i32[1] >> count.i32[1], a.i32[2] >> count.i32[2], + a.i32[3] >> count.i32[3]); +} + +PX_FORCE_INLINE VecI32V VecI32V_And(const VecI32VArg a, const VecI32VArg b) +{ + return VecI32V(a.i32[0] & b.i32[0], a.i32[1] & b.i32[1], a.i32[2] & b.i32[2], a.i32[3] & b.i32[3]); +} + +PX_FORCE_INLINE VecI32V VecI32V_Or(const VecI32VArg a, const VecI32VArg b) +{ + return VecI32V(a.i32[0] | b.i32[0], a.i32[1] | b.i32[1], a.i32[2] | b.i32[2], a.i32[3] | b.i32[3]); +} + +PX_FORCE_INLINE VecI32V VecI32V_GetX(const VecI32VArg a) +{ + return VecI32V(a.i32[0], a.i32[0], a.i32[0], a.i32[0]); +} + +PX_FORCE_INLINE VecI32V VecI32V_GetY(const VecI32VArg a) +{ + return VecI32V(a.i32[1], a.i32[1], a.i32[1], a.i32[1]); +} + +PX_FORCE_INLINE VecI32V VecI32V_GetZ(const VecI32VArg a) +{ + return VecI32V(a.i32[2], a.i32[2], a.i32[2], a.i32[2]); +} + +PX_FORCE_INLINE VecI32V VecI32V_GetW(const VecI32VArg a) +{ + return VecI32V(a.i32[3], a.i32[3], a.i32[3], a.i32[3]); +} + +PX_FORCE_INLINE VecI32V VecI32V_Sel(const BoolV c, const VecI32VArg a, const VecI32VArg b) +{ + return VecI32V(c.ux ? a.i32[0] : b.i32[0], c.uy ? a.i32[1] : b.i32[1], c.uz ? a.i32[2] : b.i32[2], + c.uw ? a.i32[3] : b.i32[3]); +} + +PX_FORCE_INLINE VecI32V VecI32V_Merge(const VecI32VArg a, const VecI32VArg b, const VecI32VArg c, const VecI32VArg d) +{ + return VecI32V(a.i32[0], b.i32[0], c.i32[0], d.i32[0]); +} + +PX_FORCE_INLINE void PxI32_From_VecI32V(const VecI32VArg a, PxI32* i) +{ + *i = a.i32[0]; +} + +PX_FORCE_INLINE VecI32V VecI32V_From_BoolV(const BoolVArg b) +{ + return VecI32V(PxI32(b.ux), PxI32(b.uy), PxI32(b.uz), PxI32(b.uw)); +} + +PX_FORCE_INLINE VecU32V VecU32V_From_BoolV(const BoolVArg b) +{ + return VecU32V(b.ux, b.uy, b.uz, b.uw); +} + +PX_FORCE_INLINE void QuatGetMat33V(const QuatVArg q, Vec3V& column0, Vec3V& column1, Vec3V& column2) +{ + const FloatV one = FOne(); + const FloatV x = V4GetX(q); + const FloatV y = V4GetY(q); + const FloatV z = V4GetZ(q); + const FloatV w = V4GetW(q); + + const FloatV x2 = FAdd(x, x); + const FloatV y2 = FAdd(y, y); + const FloatV z2 = FAdd(z, z); + + const FloatV xx = FMul(x2, x); + const FloatV yy = FMul(y2, y); + const FloatV zz = FMul(z2, z); + + const FloatV xy = FMul(x2, y); + const FloatV xz = FMul(x2, z); + const FloatV xw = FMul(x2, w); + + const FloatV yz = FMul(y2, z); + const FloatV yw = FMul(y2, w); + const FloatV zw = FMul(z2, w); + + const FloatV v = FSub(one, xx); + + column0 = V3Merge(FSub(FSub(one, yy), zz), FAdd(xy, zw), FSub(xz, yw)); + column1 = V3Merge(FSub(xy, zw), FSub(v, zz), FAdd(yz, xw)); + column2 = V3Merge(FAdd(xz, yw), FSub(yz, xw), FSub(v, yy)); +} + + +// not used + +/* +PX_FORCE_INLINE Vec4V V4LoadAligned(Vec4V* addr) +{ + return *addr; +} +*/ + +/* +PX_FORCE_INLINE Vec4V V4LoadUnaligned(Vec4V* addr) +{ + return *addr; +} +*/ + +/* +PX_FORCE_INLINE Vec4V V4Ceil(const Vec4V a) +{ + return Vec4V(PxCeil(a.x), PxCeil(a.y), PxCeil(a.z), PxCeil(a.w)); +} + +PX_FORCE_INLINE Vec4V V4Floor(const Vec4V a) +{ + return Vec4V(PxFloor(a.x), PxFloor(a.y), PxFloor(a.z), PxFloor(a.w)); +} +*/ + +/* +PX_FORCE_INLINE VecU32V V4ConvertToU32VSaturate(const Vec4V a, PxU32 power) +{ + PX_ASSERT(power == 0 && "Non-zero power not supported in convertToU32VSaturate"); + PX_UNUSED(power); // prevent warning in release builds + PxF32 ffffFFFFasFloat = PxF32(0xFFFF0000); + return VecU32V( + PxU32(PxClamp((a).x, 0.0f, ffffFFFFasFloat)), + PxU32(PxClamp((a).y, 0.0f, ffffFFFFasFloat)), + PxU32(PxClamp((a).z, 0.0f, ffffFFFFasFloat)), + PxU32(PxClamp((a).w, 0.0f, ffffFFFFasFloat))); +} +*/ + +} // namespace aos +} // namespace shdfnd +} // namespace physx + +#endif // PSFOUNDATION_PSVECMATHAOSSCALARINLINE_H diff --git a/sources/PhysX/PhysX/source/foundation/include/PsVecMathSSE.h b/sources/PhysX/PhysX/source/foundation/include/PsVecMathSSE.h new file mode 100644 index 00000000..ed3f4dee --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsVecMathSSE.h @@ -0,0 +1,68 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSVECMATHSSE_H +#define PSFOUNDATION_PSVECMATHSSE_H + +namespace physx +{ +namespace shdfnd +{ +namespace aos +{ + +namespace +{ + const PX_ALIGN(16, PxF32) minus1w[4] = { 0.0f, 0.0f, 0.0f, -1.0f }; +} + +PX_FORCE_INLINE void QuatGetMat33V(const QuatVArg q, Vec3V& column0, Vec3V& column1, Vec3V& column2) +{ + const __m128 q2 = V4Add(q, q); + const __m128 qw2 = V4MulAdd(q2, V4GetW(q), _mm_load_ps(minus1w)); // (2wx, 2wy, 2wz, 2ww-1) + const __m128 nw2 = Vec3V_From_Vec4V(V4Neg(qw2)); // (-2wx, -2wy, -2wz, 0) + const __m128 v = Vec3V_From_Vec4V(q); + + const __m128 a0 = _mm_shuffle_ps(qw2, nw2, _MM_SHUFFLE(3, 1, 2, 3)); // (2ww-1, 2wz, -2wy, 0) + column0 = V4MulAdd(v, V4GetX(q2), a0); + + const __m128 a1 = _mm_shuffle_ps(qw2, nw2, _MM_SHUFFLE(3, 2, 0, 3)); // (2ww-1, 2wx, -2wz, 0) + column1 = V4MulAdd(v, V4GetY(q2), _mm_shuffle_ps(a1, a1, _MM_SHUFFLE(3, 1, 0, 2))); + + const __m128 a2 = _mm_shuffle_ps(qw2, nw2, _MM_SHUFFLE(3, 0, 1, 3)); // (2ww-1, 2wy, -2wx, 0) + column2 = V4MulAdd(v, V4GetZ(q2), _mm_shuffle_ps(a2, a2, _MM_SHUFFLE(3, 0, 2, 1))); +} + +} // namespace aos +} // namespace shdfnd +} // namespace physx + + +#endif // PSFOUNDATION_PSVECMATHSSE_H + diff --git a/sources/PhysX/PhysX/source/foundation/include/PsVecMathUtilities.h b/sources/PhysX/PhysX/source/foundation/include/PsVecMathUtilities.h new file mode 100644 index 00000000..f3c1abba --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsVecMathUtilities.h @@ -0,0 +1,57 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSVECMATHUTILITIES_H +#define PSFOUNDATION_PSVECMATHUTILITIES_H + +#include "PsVecMath.h" + +namespace physx +{ +namespace shdfnd +{ +namespace aos +{ +/*! + Extend an edge along its length by a factor + */ +PX_FORCE_INLINE void makeFatEdge(Vec3V& p0, Vec3V& p1, const FloatVArg fatCoeff) +{ + const Vec3V delta = V3Sub(p1, p0); + const FloatV m = V3Length(delta); + const BoolV con = FIsGrtr(m, FZero()); + const Vec3V fatDelta = V3Scale(V3ScaleInv(delta, m), fatCoeff); + p0 = V3Sel(con, V3Sub(p0, fatDelta), p0); + p1 = V3Sel(con, V3Add(p1, fatDelta), p1); +} +} +} +} + +#endif diff --git a/sources/PhysX/PhysX/source/foundation/include/PsVecQuat.h b/sources/PhysX/PhysX/source/foundation/include/PsVecQuat.h new file mode 100644 index 00000000..9c295762 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsVecQuat.h @@ -0,0 +1,466 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSVECQUAT_H +#define PSFOUNDATION_PSVECQUAT_H + +//#include "PsInlineAoS.h" + +namespace physx +{ +namespace shdfnd +{ +namespace aos +{ + +#ifndef PX_PIDIV2 +#define PX_PIDIV2 1.570796327f +#endif + +////////////////////////////////// +// QuatV +////////////////////////////////// +PX_FORCE_INLINE QuatV QuatVLoadXYZW(const PxF32 x, const PxF32 y, const PxF32 z, const PxF32 w) +{ + return V4LoadXYZW(x, y, z, w); +} + +PX_FORCE_INLINE QuatV QuatVLoadU(const PxF32* v) +{ + return V4LoadU(v); +} + +PX_FORCE_INLINE QuatV QuatVLoadA(const PxF32* v) +{ + return V4LoadA(v); +} + +PX_FORCE_INLINE QuatV QuatV_From_RotationAxisAngle(const Vec3V u, const FloatV a) +{ + // q = cos(a/2) + u*sin(a/2) + const FloatV half = FLoad(0.5f); + const FloatV hangle = FMul(a, half); + const FloatV piByTwo(FLoad(PX_PIDIV2)); + const FloatV PiByTwoMinHangle(FSub(piByTwo, hangle)); + const Vec4V hangle2(Vec4V_From_Vec3V(V3Merge(hangle, PiByTwoMinHangle, hangle))); + + /*const FloatV sina = FSin(hangle); + const FloatV cosa = FCos(hangle);*/ + + const Vec4V _sina = V4Sin(hangle2); + const FloatV sina = V4GetX(_sina); + const FloatV cosa = V4GetY(_sina); + + const Vec3V v = V3Scale(u, sina); + // return V4Sel(BTTTF(), Vec4V_From_Vec3V(v), V4Splat(cosa)); + return V4SetW(Vec4V_From_Vec3V(v), cosa); +} + +// Normalize +PX_FORCE_INLINE QuatV QuatNormalize(const QuatV q) +{ + return V4Normalize(q); +} + +PX_FORCE_INLINE FloatV QuatLength(const QuatV q) +{ + return V4Length(q); +} + +PX_FORCE_INLINE FloatV QuatLengthSq(const QuatV q) +{ + return V4LengthSq(q); +} + +PX_FORCE_INLINE FloatV QuatDot(const QuatV a, const QuatV b) // convert this PxQuat to a unit quaternion +{ + return V4Dot(a, b); +} + +PX_FORCE_INLINE QuatV QuatConjugate(const QuatV q) +{ + return V4SetW(V4Neg(q), V4GetW(q)); +} + +PX_FORCE_INLINE Vec3V QuatGetImaginaryPart(const QuatV q) +{ + return Vec3V_From_Vec4V(q); +} + +/** brief computes rotation of x-axis */ +PX_FORCE_INLINE Vec3V QuatGetBasisVector0(const QuatV q) +{ + /*const PxF32 x2 = x*2.0f; + const PxF32 w2 = w*2.0f; + return PxVec3( (w * w2) - 1.0f + x*x2, + (z * w2) + y*x2, + (-y * w2) + z*x2);*/ + + const FloatV two = FLoad(2.f); + const FloatV w = V4GetW(q); + const Vec3V u = Vec3V_From_Vec4V(q); + + const FloatV x2 = FMul(V3GetX(u), two); + const FloatV w2 = FMul(w, two); + + const Vec3V a = V3Scale(u, x2); + const Vec3V tmp = V3Merge(w, V3GetZ(u), FNeg(V3GetY(u))); + // const Vec3V b = V3Scale(tmp, w2); + // const Vec3V ab = V3Add(a, b); + const Vec3V ab = V3ScaleAdd(tmp, w2, a); + return V3SetX(ab, FSub(V3GetX(ab), FOne())); +} + +/** brief computes rotation of y-axis */ +PX_FORCE_INLINE Vec3V QuatGetBasisVector1(const QuatV q) +{ + /*const PxF32 y2 = y*2.0f; + const PxF32 w2 = w*2.0f; + return PxVec3( (-z * w2) + x*y2, + (w * w2) - 1.0f + y*y2, + (x * w2) + z*y2);*/ + + const FloatV two = FLoad(2.f); + const FloatV w = V4GetW(q); + const Vec3V u = Vec3V_From_Vec4V(q); + + const FloatV y2 = FMul(V3GetY(u), two); + const FloatV w2 = FMul(w, two); + + const Vec3V a = V3Scale(u, y2); + const Vec3V tmp = V3Merge(FNeg(V3GetZ(u)), w, V3GetX(u)); + // const Vec3V b = V3Scale(tmp, w2); + // const Vec3V ab = V3Add(a, b); + const Vec3V ab = V3ScaleAdd(tmp, w2, a); + return V3SetY(ab, FSub(V3GetY(ab), FOne())); +} + +/** brief computes rotation of z-axis */ +PX_FORCE_INLINE Vec3V QuatGetBasisVector2(const QuatV q) +{ + /*const PxF32 z2 = z*2.0f; + const PxF32 w2 = w*2.0f; + return PxVec3( (y * w2) + x*z2, + (-x * w2) + y*z2, + (w * w2) - 1.0f + z*z2);*/ + + const FloatV two = FLoad(2.f); + const FloatV w = V4GetW(q); + const Vec3V u = Vec3V_From_Vec4V(q); + + const FloatV z2 = FMul(V3GetZ(u), two); + const FloatV w2 = FMul(w, two); + + const Vec3V a = V3Scale(u, z2); + const Vec3V tmp = V3Merge(V3GetY(u), FNeg(V3GetX(u)), w); + /*const Vec3V b = V3Scale(tmp, w2); + const Vec3V ab = V3Add(a, b);*/ + const Vec3V ab = V3ScaleAdd(tmp, w2, a); + return V3SetZ(ab, FSub(V3GetZ(ab), FOne())); +} + +PX_FORCE_INLINE Vec3V QuatRotate(const QuatV q, const Vec3V v) +{ + /* + const PxVec3 qv(x,y,z); + return (v*(w*w-0.5f) + (qv.cross(v))*w + qv*(qv.dot(v)))*2; + */ + + const FloatV two = FLoad(2.f); + // const FloatV half = FloatV_From_F32(0.5f); + const FloatV nhalf = FLoad(-0.5f); + const Vec3V u = Vec3V_From_Vec4V(q); + const FloatV w = V4GetW(q); + // const FloatV w2 = FSub(FMul(w, w), half); + const FloatV w2 = FScaleAdd(w, w, nhalf); + const Vec3V a = V3Scale(v, w2); + // const Vec3V b = V3Scale(V3Cross(u, v), w); + // const Vec3V c = V3Scale(u, V3Dot(u, v)); + // return V3Scale(V3Add(V3Add(a, b), c), two); + const Vec3V temp = V3ScaleAdd(V3Cross(u, v), w, a); + return V3Scale(V3ScaleAdd(u, V3Dot(u, v), temp), two); +} + +PX_FORCE_INLINE Vec3V QuatTransform(const QuatV q, const Vec3V p, const Vec3V v) +{ + // p + q.rotate(v) + const FloatV two = FLoad(2.f); + // const FloatV half = FloatV_From_F32(0.5f); + const FloatV nhalf = FLoad(-0.5f); + const Vec3V u = Vec3V_From_Vec4V(q); + const FloatV w = V4GetW(q); + // const FloatV w2 = FSub(FMul(w, w), half); + const FloatV w2 = FScaleAdd(w, w, nhalf); + const Vec3V a = V3Scale(v, w2); + /*const Vec3V b = V3Scale(V3Cross(u, v), w); + const Vec3V c = V3Scale(u, V3Dot(u, v)); + return V3ScaleAdd(V3Add(V3Add(a, b), c), two, p);*/ + const Vec3V temp = V3ScaleAdd(V3Cross(u, v), w, a); + const Vec3V z = V3ScaleAdd(u, V3Dot(u, v), temp); + return V3ScaleAdd(z, two, p); +} + +PX_FORCE_INLINE Vec3V QuatRotateInv(const QuatV q, const Vec3V v) +{ + + // const PxVec3 qv(x,y,z); + // return (v*(w*w-0.5f) - (qv.cross(v))*w + qv*(qv.dot(v)))*2; + + const FloatV two = FLoad(2.f); + const FloatV nhalf = FLoad(-0.5f); + const Vec3V u = Vec3V_From_Vec4V(q); + const FloatV w = V4GetW(q); + const FloatV w2 = FScaleAdd(w, w, nhalf); + const Vec3V a = V3Scale(v, w2); + /*const Vec3V b = V3Scale(V3Cross(u, v), w); + const Vec3V c = V3Scale(u, V3Dot(u, v)); + return V3Scale(V3Add(V3Sub(a, b), c), two);*/ + const Vec3V temp = V3NegScaleSub(V3Cross(u, v), w, a); + return V3Scale(V3ScaleAdd(u, V3Dot(u, v), temp), two); +} + +PX_FORCE_INLINE QuatV QuatMul(const QuatV a, const QuatV b) +{ + const Vec3V imagA = Vec3V_From_Vec4V(a); + const Vec3V imagB = Vec3V_From_Vec4V(b); + const FloatV rA = V4GetW(a); + const FloatV rB = V4GetW(b); + + const FloatV real = FSub(FMul(rA, rB), V3Dot(imagA, imagB)); + const Vec3V v0 = V3Scale(imagA, rB); + const Vec3V v1 = V3Scale(imagB, rA); + const Vec3V v2 = V3Cross(imagA, imagB); + const Vec3V imag = V3Add(V3Add(v0, v1), v2); + + return V4SetW(Vec4V_From_Vec3V(imag), real); +} + +PX_FORCE_INLINE QuatV QuatAdd(const QuatV a, const QuatV b) +{ + return V4Add(a, b); +} + +PX_FORCE_INLINE QuatV QuatNeg(const QuatV q) +{ + return V4Neg(q); +} + +PX_FORCE_INLINE QuatV QuatSub(const QuatV a, const QuatV b) +{ + return V4Sub(a, b); +} + +PX_FORCE_INLINE QuatV QuatScale(const QuatV a, const FloatV b) +{ + return V4Scale(a, b); +} + +PX_FORCE_INLINE QuatV QuatMerge(const FloatV* const floatVArray) +{ + return V4Merge(floatVArray); +} + +PX_FORCE_INLINE QuatV QuatMerge(const FloatVArg x, const FloatVArg y, const FloatVArg z, const FloatVArg w) +{ + return V4Merge(x, y, z, w); +} + +PX_FORCE_INLINE QuatV QuatIdentity() +{ + return V4SetW(V4Zero(), FOne()); +} + +PX_FORCE_INLINE bool isFiniteQuatV(const QuatV q) +{ + return isFiniteVec4V(q); +} + +PX_FORCE_INLINE bool isValidQuatV(const QuatV q) +{ + const FloatV unitTolerance = FLoad(1e-4f); + const FloatV tmp = FAbs(FSub(QuatLength(q), FOne())); + const BoolV con = FIsGrtr(unitTolerance, tmp); + return isFiniteVec4V(q) & (BAllEqTTTT(con) == 1); +} + +PX_FORCE_INLINE bool isSaneQuatV(const QuatV q) +{ + const FloatV unitTolerance = FLoad(1e-2f); + const FloatV tmp = FAbs(FSub(QuatLength(q), FOne())); + const BoolV con = FIsGrtr(unitTolerance, tmp); + return isFiniteVec4V(q) & (BAllEqTTTT(con) == 1); +} + +PX_FORCE_INLINE Mat33V QuatGetMat33V(const QuatVArg q) +{ + // const FloatV two = FloatV_From_F32(2.f); + // const FloatV one = FOne(); + + // const FloatV x = V4GetX(q); + // const FloatV y = V4GetY(q); + // const FloatV z = V4GetZ(q); + // const Vec4V _q = V4Mul(q, two); + // + ////const FloatV w = V4GetW(q); + + // const Vec4V t0 = V4Mul(_q, x); // 2xx, 2xy, 2xz, 2xw + // const Vec4V t1 = V4Mul(_q, y); // 2xy, 2yy, 2yz, 2yw + // const Vec4V t2 = V4Mul(_q, z); // 2xz, 2yz, 2zz, 2zw + ////const Vec4V t3 = V4Mul(_q, w); // 2xw, 2yw, 2zw, 2ww + + // const FloatV xx2 = V4GetX(t0); + // const FloatV xy2 = V4GetY(t0); + // const FloatV xz2 = V4GetZ(t0); + // const FloatV xw2 = V4GetW(t0); + + // const FloatV yy2 = V4GetY(t1); + // const FloatV yz2 = V4GetZ(t1); + // const FloatV yw2 = V4GetW(t1); + + // const FloatV zz2 = V4GetZ(t2); + // const FloatV zw2 = V4GetW(t2); + + ////const FloatV ww2 = V4GetW(t3); + + // const FloatV c00 = FSub(one, FAdd(yy2, zz2)); + // const FloatV c01 = FSub(xy2, zw2); + // const FloatV c02 = FAdd(xz2, yw2); + + // const FloatV c10 = FAdd(xy2, zw2); + // const FloatV c11 = FSub(one, FAdd(xx2, zz2)); + // const FloatV c12 = FSub(yz2, xw2); + + // const FloatV c20 = FSub(xz2, yw2); + // const FloatV c21 = FAdd(yz2, xw2); + // const FloatV c22 = FSub(one, FAdd(xx2, yy2)); + + // const Vec3V c0 = V3Merge(c00, c10, c20); + // const Vec3V c1 = V3Merge(c01, c11, c21); + // const Vec3V c2 = V3Merge(c02, c12, c22); + + // return Mat33V(c0, c1, c2); + + const FloatV one = FOne(); + const FloatV x = V4GetX(q); + const FloatV y = V4GetY(q); + const FloatV z = V4GetZ(q); + const FloatV w = V4GetW(q); + + const FloatV x2 = FAdd(x, x); + const FloatV y2 = FAdd(y, y); + const FloatV z2 = FAdd(z, z); + + const FloatV xx = FMul(x2, x); + const FloatV yy = FMul(y2, y); + const FloatV zz = FMul(z2, z); + + const FloatV xy = FMul(x2, y); + const FloatV xz = FMul(x2, z); + const FloatV xw = FMul(x2, w); + + const FloatV yz = FMul(y2, z); + const FloatV yw = FMul(y2, w); + const FloatV zw = FMul(z2, w); + + const FloatV v = FSub(one, xx); + + const Vec3V column0 = V3Merge(FSub(FSub(one, yy), zz), FAdd(xy, zw), FSub(xz, yw)); + const Vec3V column1 = V3Merge(FSub(xy, zw), FSub(v, zz), FAdd(yz, xw)); + const Vec3V column2 = V3Merge(FAdd(xz, yw), FSub(yz, xw), FSub(v, yy)); + return Mat33V(column0, column1, column2); +} + +PX_FORCE_INLINE QuatV Mat33GetQuatV(const Mat33V& a) +{ + const FloatV one = FOne(); + const FloatV zero = FZero(); + const FloatV half = FLoad(0.5f); + const FloatV two = FLoad(2.f); + const FloatV scale = FLoad(0.25f); + const FloatV a00 = V3GetX(a.col0); + const FloatV a11 = V3GetY(a.col1); + const FloatV a22 = V3GetZ(a.col2); + + const FloatV a21 = V3GetZ(a.col1); // row=2, col=1; + const FloatV a12 = V3GetY(a.col2); // row=1, col=2; + const FloatV a02 = V3GetX(a.col2); // row=0, col=2; + const FloatV a20 = V3GetZ(a.col0); // row=2, col=0; + const FloatV a10 = V3GetY(a.col0); // row=1, col=0; + const FloatV a01 = V3GetX(a.col1); // row=0, col=1; + + const Vec3V vec0 = V3Merge(a21, a02, a10); + const Vec3V vec1 = V3Merge(a12, a20, a01); + const Vec3V v = V3Sub(vec0, vec1); + const Vec3V g = V3Add(vec0, vec1); + + const FloatV trace = FAdd(a00, FAdd(a11, a22)); + + if(FAllGrtrOrEq(trace, zero)) + { + const FloatV h = FSqrt(FAdd(trace, one)); + const FloatV w = FMul(half, h); + const FloatV s = FMul(half, FRecip(h)); + const Vec3V u = V3Scale(v, s); + return V4SetW(Vec4V_From_Vec3V(u), w); + } + else + { + const FloatV ntrace = FNeg(trace); + const Vec3V d = V3Merge(a00, a11, a22); + const BoolV con0 = BAllTrue3(V3IsGrtrOrEq(V3Splat(a00), d)); + const BoolV con1 = BAllTrue3(V3IsGrtrOrEq(V3Splat(a11), d)); + + const FloatV t0 = FAdd(one, FScaleAdd(a00, two, ntrace)); + const FloatV t1 = FAdd(one, FScaleAdd(a11, two, ntrace)); + const FloatV t2 = FAdd(one, FScaleAdd(a22, two, ntrace)); + + const FloatV t = FSel(con0, t0, FSel(con1, t1, t2)); + + const FloatV h = FMul(two, FSqrt(t)); + const FloatV s = FRecip(h); + const FloatV g0 = FMul(scale, h); + const Vec3V vs = V3Scale(v, s); + const Vec3V gs = V3Scale(g, s); + const FloatV gsx = V3GetX(gs); + const FloatV gsy = V3GetY(gs); + const FloatV gsz = V3GetZ(gs); + // vs.x= (a21 - a12)*s; vs.y=(a02 - a20)*s; vs.z=(a10 - a01)*s; + // gs.x= (a21 + a12)*s; gs.y=(a02 + a20)*s; gs.z=(a10 + a01)*s; + const Vec4V v0 = V4Merge(g0, gsz, gsy, V3GetX(vs)); + const Vec4V v1 = V4Merge(gsz, g0, gsx, V3GetY(vs)); + const Vec4V v2 = V4Merge(gsy, gsx, g0, V3GetZ(vs)); + return V4Sel(con0, v0, V4Sel(con1, v1, v2)); + } +} + +} // namespace aos +} // namespace shdfnd +} // namespace physx + +#endif diff --git a/sources/PhysX/PhysX/source/foundation/include/PsVecTransform.h b/sources/PhysX/PhysX/source/foundation/include/PsVecTransform.h new file mode 100644 index 00000000..48a2f8aa --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/PsVecTransform.h @@ -0,0 +1,283 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSVECTRANSFORM_H +#define PSFOUNDATION_PSVECTRANSFORM_H + +#include "PsVecMath.h" +#include "foundation/PxTransform.h" + +namespace physx +{ +namespace shdfnd +{ +namespace aos +{ + +class PsTransformV +{ + public: + QuatV q; + Vec3V p; + + PX_FORCE_INLINE PsTransformV(const PxTransform& orientation) + { + // const PxQuat oq = orientation.q; + // const PxF32 f[4] = {oq.x, oq.y, oq.z, oq.w}; + q = QuatVLoadXYZW(orientation.q.x, orientation.q.y, orientation.q.z, orientation.q.w); + // q = QuatV_From_F32Array(&oq.x); + p = V3LoadU(orientation.p); + } + + PX_FORCE_INLINE PsTransformV(const Vec3VArg p0 = V3Zero(), const QuatVArg q0 = QuatIdentity()) : q(q0), p(p0) + { + PX_ASSERT(isSaneQuatV(q0)); + } + + PX_FORCE_INLINE PsTransformV operator*(const PsTransformV& x) const + { + PX_ASSERT(x.isSane()); + return transform(x); + } + + PX_FORCE_INLINE PsTransformV getInverse() const + { + PX_ASSERT(isFinite()); + // return PxTransform(q.rotateInv(-p),q.getConjugate()); + return PsTransformV(QuatRotateInv(q, V3Neg(p)), QuatConjugate(q)); + } + + PX_FORCE_INLINE void normalize() + { + p = V3Zero(); + q = QuatIdentity(); + } + + PX_FORCE_INLINE void Invalidate() + { + p = V3Splat(FMax()); + q = QuatIdentity(); + } + + PX_FORCE_INLINE Vec3V transform(const Vec3VArg input) const + { + PX_ASSERT(isFinite()); + // return q.rotate(input) + p; + return QuatTransform(q, p, input); + } + + PX_FORCE_INLINE Vec3V transformInv(const Vec3VArg input) const + { + PX_ASSERT(isFinite()); + // return q.rotateInv(input-p); + return QuatRotateInv(q, V3Sub(input, p)); + } + + PX_FORCE_INLINE Vec3V rotate(const Vec3VArg input) const + { + PX_ASSERT(isFinite()); + // return q.rotate(input); + return QuatRotate(q, input); + } + + PX_FORCE_INLINE Vec3V rotateInv(const Vec3VArg input) const + { + PX_ASSERT(isFinite()); + // return q.rotateInv(input); + return QuatRotateInv(q, input); + } + + //! Transform transform to parent (returns compound transform: first src, then *this) + PX_FORCE_INLINE PsTransformV transform(const PsTransformV& src) const + { + PX_ASSERT(src.isSane()); + PX_ASSERT(isSane()); + // src = [srct, srcr] -> [r*srct + t, r*srcr] + // return PxTransform(q.rotate(src.p) + p, q*src.q); + return PsTransformV(V3Add(QuatRotate(q, src.p), p), QuatMul(q, src.q)); + } + + /** + \brief returns true if finite and q is a unit quaternion + */ + + PX_FORCE_INLINE bool isValid() const + { + // return p.isFinite() && q.isFinite() && q.isValid(); + return isFiniteVec3V(p) & isFiniteQuatV(q) & isValidQuatV(q); + } + + /** + \brief returns true if finite and quat magnitude is reasonably close to unit to allow for some accumulation of error + vs isValid + */ + + PX_FORCE_INLINE bool isSane() const + { + // return isFinite() && q.isSane(); + return isFinite() & isSaneQuatV(q); + } + + /** + \brief returns true if all elems are finite (not NAN or INF, etc.) + */ + PX_FORCE_INLINE bool isFinite() const + { + // return p.isFinite() && q.isFinite(); + return isFiniteVec3V(p) & isFiniteQuatV(q); + } + + //! Transform transform from parent (returns compound transform: first src, then this->inverse) + PX_FORCE_INLINE PsTransformV transformInv(const PsTransformV& src) const + { + PX_ASSERT(src.isSane()); + PX_ASSERT(isFinite()); + // src = [srct, srcr] -> [r^-1*(srct-t), r^-1*srcr] + /*PxQuat qinv = q.getConjugate(); + return PxTransform(qinv.rotate(src.p - p), qinv*src.q);*/ + const QuatV qinv = QuatConjugate(q); + const Vec3V v = QuatRotate(qinv, V3Sub(src.p, p)); + const QuatV rot = QuatMul(qinv, src.q); + return PsTransformV(v, rot); + } + + static PX_FORCE_INLINE PsTransformV createIdentity() + { + return PsTransformV(V3Zero()); + } +}; + +PX_FORCE_INLINE PsTransformV loadTransformA(const PxTransform& transform) +{ + const QuatV q0 = QuatVLoadA(&transform.q.x); + const Vec3V p0 = V3LoadA(&transform.p.x); + + return PsTransformV(p0, q0); +} + +PX_FORCE_INLINE PsTransformV loadTransformU(const PxTransform& transform) +{ + const QuatV q0 = QuatVLoadU(&transform.q.x); + const Vec3V p0 = V3LoadU(&transform.p.x); + + return PsTransformV(p0, q0); +} + +class PsMatTransformV +{ + public: + Mat33V rot; + Vec3V p; + + PX_FORCE_INLINE PsMatTransformV() + { + p = V3Zero(); + rot = M33Identity(); + } + PX_FORCE_INLINE PsMatTransformV(const Vec3VArg _p, const Mat33V& _rot) + { + p = _p; + rot = _rot; + } + + PX_FORCE_INLINE PsMatTransformV(const PsTransformV& other) + { + p = other.p; + QuatGetMat33V(other.q, rot.col0, rot.col1, rot.col2); + } + + PX_FORCE_INLINE PsMatTransformV(const Vec3VArg _p, const QuatV& quat) + { + p = _p; + QuatGetMat33V(quat, rot.col0, rot.col1, rot.col2); + } + + PX_FORCE_INLINE Vec3V getCol0() const + { + return rot.col0; + } + + PX_FORCE_INLINE Vec3V getCol1() const + { + return rot.col1; + } + + PX_FORCE_INLINE Vec3V getCol2() const + { + return rot.col2; + } + + PX_FORCE_INLINE void setCol0(const Vec3VArg col0) + { + rot.col0 = col0; + } + + PX_FORCE_INLINE void setCol1(const Vec3VArg col1) + { + rot.col1 = col1; + } + + PX_FORCE_INLINE void setCol2(const Vec3VArg col2) + { + rot.col2 = col2; + } + + PX_FORCE_INLINE Vec3V transform(const Vec3VArg input) const + { + return V3Add(p, M33MulV3(rot, input)); + } + + PX_FORCE_INLINE Vec3V transformInv(const Vec3VArg input) const + { + return M33TrnspsMulV3(rot, V3Sub(input, p)); // QuatRotateInv(q, V3Sub(input, p)); + } + + PX_FORCE_INLINE Vec3V rotate(const Vec3VArg input) const + { + return M33MulV3(rot, input); + } + + PX_FORCE_INLINE Vec3V rotateInv(const Vec3VArg input) const + { + return M33TrnspsMulV3(rot, input); + } + + PX_FORCE_INLINE PsMatTransformV transformInv(const PsMatTransformV& src) const + { + + const Vec3V v = M33TrnspsMulV3(rot, V3Sub(src.p, p)); + const Mat33V mat = M33MulM33(M33Trnsps(rot), src.rot); + return PsMatTransformV(v, mat); + } +}; +} +} +} + +#endif diff --git a/sources/PhysX/PhysX/source/foundation/include/unix/PsUnixAoS.h b/sources/PhysX/PhysX/source/foundation/include/unix/PsUnixAoS.h new file mode 100644 index 00000000..184d7d40 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/unix/PsUnixAoS.h @@ -0,0 +1,47 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSUNIXAOS_H +#define PSFOUNDATION_PSUNIXAOS_H + +// no includes here! this file should be included from PxcVecMath.h only!!! + +#if !COMPILE_VECTOR_INTRINSICS +#error Vector intrinsics should not be included when using scalar implementation. +#endif + +#if PX_INTEL_FAMILY +#include "sse2/PsUnixSse2AoS.h" +#elif PX_NEON +#include "neon/PsUnixNeonAoS.h" +#else +#error No SIMD implementation for this unix platform. +#endif + +#endif // PSFOUNDATION_PSUNIXAOS_H diff --git a/sources/PhysX/PhysX/source/foundation/include/unix/PsUnixFPU.h b/sources/PhysX/PhysX/source/foundation/include/unix/PsUnixFPU.h new file mode 100644 index 00000000..fad9e84e --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/unix/PsUnixFPU.h @@ -0,0 +1,68 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSUNIXFPU_H +#define PSFOUNDATION_PSUNIXFPU_H + +#include "foundation/PxPreprocessor.h" + +#if PX_LINUX || PX_PS4 || PX_OSX + +#if PX_X86 || PX_X64 +#if PX_EMSCRIPTEN +#include +#endif +#include +#elif PX_NEON +#include +#endif + +PX_INLINE physx::shdfnd::SIMDGuard::SIMDGuard() +{ +#if !PX_EMSCRIPTEN && (PX_X86 || PX_X64) + mControlWord = _mm_getcsr(); + // set default (disable exceptions: _MM_MASK_MASK) and FTZ (_MM_FLUSH_ZERO_ON), DAZ (_MM_DENORMALS_ZERO_ON: (1<<6)) + _mm_setcsr(_MM_MASK_MASK | _MM_FLUSH_ZERO_ON | (1 << 6)); +#endif +} + +PX_INLINE physx::shdfnd::SIMDGuard::~SIMDGuard() +{ +#if !PX_EMSCRIPTEN && (PX_X86 || PX_X64) + // restore control word and clear exception flags + // (setting exception state flags cause exceptions on the first following fp operation) + _mm_setcsr(mControlWord & ~_MM_EXCEPT_MASK); +#endif +} + +#else + #error No SIMD implementation for this unix platform. +#endif // PX_LINUX || PX_PS4 || PX_OSX + +#endif // #ifndef PSFOUNDATION_PSUNIXFPU_H diff --git a/sources/PhysX/PhysX/source/foundation/include/unix/PsUnixInlineAoS.h b/sources/PhysX/PhysX/source/foundation/include/unix/PsUnixInlineAoS.h new file mode 100644 index 00000000..e562e0e0 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/unix/PsUnixInlineAoS.h @@ -0,0 +1,45 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSUNIXINLINEAOS_H +#define PSFOUNDATION_PSUNIXINLINEAOS_H + +#if !COMPILE_VECTOR_INTRINSICS +#error Vector intrinsics should not be included when using scalar implementation. +#endif + +#if PX_INTEL_FAMILY +#include "sse2/PsUnixSse2InlineAoS.h" +#elif PX_NEON +#include "neon/PsUnixNeonInlineAoS.h" +#else +#error No SIMD implementation for this unix platform. +#endif + +#endif // PSFOUNDATION_PSUNIXINLINEAOS_H diff --git a/sources/PhysX/PhysX/source/foundation/include/unix/PsUnixIntrinsics.h b/sources/PhysX/PhysX/source/foundation/include/unix/PsUnixIntrinsics.h new file mode 100644 index 00000000..b84d19b9 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/unix/PsUnixIntrinsics.h @@ -0,0 +1,153 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSUNIXINTRINSICS_H +#define PSFOUNDATION_PSUNIXINTRINSICS_H + +#include "Ps.h" +#include "foundation/PxAssert.h" +#include + +#if PX_ANDROID +#include // for Ns::debugBreak() { raise(SIGTRAP); } +#endif + +#if 0 +#include +#endif + +// this file is for internal intrinsics - that is, intrinsics that are used in +// cross platform code but do not appear in the API + +#if !(PX_LINUX || PX_ANDROID || PX_PS4 || PX_APPLE_FAMILY) +#error "This file should only be included by unix builds!!" +#endif + +namespace physx +{ +namespace shdfnd +{ + +PX_FORCE_INLINE void memoryBarrier() +{ + __sync_synchronize(); +} + +/*! +Return the index of the highest set bit. Undefined for zero arg. +*/ +PX_INLINE uint32_t highestSetBitUnsafe(uint32_t v) +{ + + return 31 - __builtin_clz(v); +} + +/*! +Return the index of the highest set bit. Undefined for zero arg. +*/ +PX_INLINE int32_t lowestSetBitUnsafe(uint32_t v) +{ + return __builtin_ctz(v); +} + +/*! +Returns the index of the highest set bit. Returns 32 for v=0. +*/ +PX_INLINE uint32_t countLeadingZeros(uint32_t v) +{ + if(v) + return __builtin_clz(v); + else + return 32; +} + +/*! +Prefetch aligned 64B x86, 32b ARM around \c ptr+offset. +*/ +PX_FORCE_INLINE void prefetchLine(const void* ptr, uint32_t offset = 0) +{ + __builtin_prefetch(reinterpret_cast(ptr) + offset, 0, 3); +} + +/*! +Prefetch \c count bytes starting at \c ptr. +*/ +#if PX_ANDROID || PX_IOS +PX_FORCE_INLINE void prefetch(const void* ptr, uint32_t count = 1) +{ + const char* cp = static_cast(ptr); + size_t p = reinterpret_cast(ptr); + uint32_t startLine = uint32_t(p >> 5), endLine = uint32_t((p + count - 1) >> 5); + uint32_t lines = endLine - startLine + 1; + do + { + prefetchLine(cp); + cp += 32; + } while(--lines); +} +#else +PX_FORCE_INLINE void prefetch(const void* ptr, uint32_t count = 1) +{ + const char* cp = reinterpret_cast(ptr); + uint64_t p = size_t(ptr); + uint64_t startLine = p >> 6, endLine = (p + count - 1) >> 6; + uint64_t lines = endLine - startLine + 1; + do + { + prefetchLine(cp); + cp += 64; + } while(--lines); +} +#endif + +//! \brief platform-specific reciprocal +PX_CUDA_CALLABLE PX_FORCE_INLINE float recipFast(float a) +{ + return 1.0f / a; +} + +//! \brief platform-specific fast reciprocal square root +PX_CUDA_CALLABLE PX_FORCE_INLINE float recipSqrtFast(float a) +{ + return 1.0f / ::sqrtf(a); +} + +//! \brief platform-specific floor +PX_CUDA_CALLABLE PX_FORCE_INLINE float floatFloor(float x) +{ + return ::floorf(x); +} + +#define NS_EXPECT_TRUE(x) x +#define NS_EXPECT_FALSE(x) x + +} // namespace shdfnd +} // namespace physx + +#endif // #ifndef PSFOUNDATION_PSUNIXINTRINSICS_H diff --git a/sources/PhysX/PhysX/source/foundation/include/unix/PsUnixTrigConstants.h b/sources/PhysX/PhysX/source/foundation/include/unix/PsUnixTrigConstants.h new file mode 100644 index 00000000..ee83aa71 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/unix/PsUnixTrigConstants.h @@ -0,0 +1,98 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSUNIXTRIGCONSTANTS_H +#define PSFOUNDATION_PSUNIXTRIGCONSTANTS_H + +#include "foundation/PxPreprocessor.h" + +namespace physx +{ +namespace shdfnd +{ +namespace aos +{ + +#if PX_UWP +#define PX_GLOBALCONST extern const __declspec(selectany) +#else +#define PX_GLOBALCONST extern const __attribute__((weak)) +#endif + +PX_ALIGN_PREFIX(16) +struct PX_VECTORF32 +{ + float f[4]; +} PX_ALIGN_SUFFIX(16); + +PX_GLOBALCONST PX_VECTORF32 g_PXSinCoefficients0 = { { 1.0f, -0.166666667f, 8.333333333e-3f, -1.984126984e-4f } }; +PX_GLOBALCONST PX_VECTORF32 +g_PXSinCoefficients1 = { { 2.755731922e-6f, -2.505210839e-8f, 1.605904384e-10f, -7.647163732e-13f } }; +PX_GLOBALCONST PX_VECTORF32 +g_PXSinCoefficients2 = { { 2.811457254e-15f, -8.220635247e-18f, 1.957294106e-20f, -3.868170171e-23f } }; +PX_GLOBALCONST PX_VECTORF32 g_PXCosCoefficients0 = { { 1.0f, -0.5f, 4.166666667e-2f, -1.388888889e-3f } }; +PX_GLOBALCONST PX_VECTORF32 +g_PXCosCoefficients1 = { { 2.480158730e-5f, -2.755731922e-7f, 2.087675699e-9f, -1.147074560e-11f } }; +PX_GLOBALCONST PX_VECTORF32 +g_PXCosCoefficients2 = { { 4.779477332e-14f, -1.561920697e-16f, 4.110317623e-19f, -8.896791392e-22f } }; +PX_GLOBALCONST PX_VECTORF32 g_PXTanCoefficients0 = { { 1.0f, 0.333333333f, 0.133333333f, 5.396825397e-2f } }; +PX_GLOBALCONST PX_VECTORF32 +g_PXTanCoefficients1 = { { 2.186948854e-2f, 8.863235530e-3f, 3.592128167e-3f, 1.455834485e-3f } }; +PX_GLOBALCONST PX_VECTORF32 +g_PXTanCoefficients2 = { { 5.900274264e-4f, 2.391290764e-4f, 9.691537707e-5f, 3.927832950e-5f } }; +PX_GLOBALCONST PX_VECTORF32 +g_PXASinCoefficients0 = { { -0.05806367563904f, -0.41861972469416f, 0.22480114791621f, 2.17337241360606f } }; +PX_GLOBALCONST PX_VECTORF32 +g_PXASinCoefficients1 = { { 0.61657275907170f, 4.29696498283455f, -1.18942822255452f, -6.53784832094831f } }; +PX_GLOBALCONST PX_VECTORF32 +g_PXASinCoefficients2 = { { -1.36926553863413f, -4.48179294237210f, 1.41810672941833f, 5.48179257935713f } }; +PX_GLOBALCONST PX_VECTORF32 g_PXATanCoefficients0 = { { 1.0f, 0.333333334f, 0.2f, 0.142857143f } }; +PX_GLOBALCONST PX_VECTORF32 +g_PXATanCoefficients1 = { { 1.111111111e-1f, 9.090909091e-2f, 7.692307692e-2f, 6.666666667e-2f } }; +PX_GLOBALCONST PX_VECTORF32 +g_PXATanCoefficients2 = { { 5.882352941e-2f, 5.263157895e-2f, 4.761904762e-2f, 4.347826087e-2f } }; +PX_GLOBALCONST PX_VECTORF32 +g_PXSinEstCoefficients = { { 1.0f, -1.66521856991541e-1f, 8.199913018755e-3f, -1.61475937228e-4f } }; +PX_GLOBALCONST PX_VECTORF32 +g_PXCosEstCoefficients = { { 1.0f, -4.95348008918096e-1f, 3.878259962881e-2f, -9.24587976263e-4f } }; +PX_GLOBALCONST PX_VECTORF32 g_PXTanEstCoefficients = { { 2.484f, -1.954923183e-1f, 2.467401101f, PxInvPi } }; +PX_GLOBALCONST PX_VECTORF32 +g_PXATanEstCoefficients = { { 7.689891418951e-1f, 1.104742493348f, 8.661844266006e-1f, PxPiDivTwo } }; +PX_GLOBALCONST PX_VECTORF32 +g_PXASinEstCoefficients = { { -1.36178272886711f, 2.37949493464538f, -8.08228565650486e-1f, 2.78440142746736e-1f } }; +PX_GLOBALCONST PX_VECTORF32 g_PXASinEstConstants = { { 1.00000011921f, PxPiDivTwo, 0.0f, 0.0f } }; +PX_GLOBALCONST PX_VECTORF32 g_PXPiConstants0 = { { PxPi, PxTwoPi, PxInvPi, PxInvTwoPi } }; +PX_GLOBALCONST PX_VECTORF32 g_PXReciprocalTwoPi = { { PxInvTwoPi, PxInvTwoPi, PxInvTwoPi, PxInvTwoPi } }; +PX_GLOBALCONST PX_VECTORF32 g_PXTwoPi = { { PxTwoPi, PxTwoPi, PxTwoPi, PxTwoPi } }; + +} // namespace aos +} // namespace shdfnd +} // namespace physx + +#endif diff --git a/sources/PhysX/PhysX/source/foundation/include/unix/neon/PsUnixNeonAoS.h b/sources/PhysX/PhysX/source/foundation/include/unix/neon/PsUnixNeonAoS.h new file mode 100644 index 00000000..8d427377 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/unix/neon/PsUnixNeonAoS.h @@ -0,0 +1,140 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSUNIXNEONAOS_H +#define PSFOUNDATION_PSUNIXNEONAOS_H + +// no includes here! this file should be included from PxcVecMath.h only!!! + +#if !COMPILE_VECTOR_INTRINSICS +#error Vector intrinsics should not be included when using scalar implementation. +#endif + +// only ARM NEON compatible platforms should reach this +#include + +namespace physx +{ +namespace shdfnd +{ +namespace aos +{ + +typedef float32x2_t FloatV; +typedef float32x4_t Vec3V; +typedef float32x4_t Vec4V; +typedef uint32x4_t BoolV; +typedef float32x4_t QuatV; + +typedef uint32x4_t VecU32V; +typedef int32x4_t VecI32V; +typedef uint16x8_t VecU16V; +typedef int16x8_t VecI16V; +typedef uint8x16_t VecU8V; + +#define FloatVArg FloatV & +#define Vec3VArg Vec3V & +#define Vec4VArg Vec4V & +#define BoolVArg BoolV & +#define VecU32VArg VecU32V & +#define VecI32VArg VecI32V & +#define VecU16VArg VecU16V & +#define VecI16VArg VecI16V & +#define VecU8VArg VecU8V & +#define QuatVArg QuatV & + +// KS - TODO - make an actual VecCrossV type for NEON +#define VecCrossV Vec3V + +typedef VecI32V VecShiftV; +#define VecShiftVArg VecShiftV & + +PX_ALIGN_PREFIX(16) +struct Mat33V +{ + Mat33V() + { + } + Mat33V(const Vec3V& c0, const Vec3V& c1, const Vec3V& c2) : col0(c0), col1(c1), col2(c2) + { + } + Vec3V PX_ALIGN(16, col0); + Vec3V PX_ALIGN(16, col1); + Vec3V PX_ALIGN(16, col2); +} PX_ALIGN_SUFFIX(16); + +PX_ALIGN_PREFIX(16) +struct Mat34V +{ + Mat34V() + { + } + Mat34V(const Vec3V& c0, const Vec3V& c1, const Vec3V& c2, const Vec3V& c3) : col0(c0), col1(c1), col2(c2), col3(c3) + { + } + Vec3V PX_ALIGN(16, col0); + Vec3V PX_ALIGN(16, col1); + Vec3V PX_ALIGN(16, col2); + Vec3V PX_ALIGN(16, col3); +} PX_ALIGN_SUFFIX(16); + +PX_ALIGN_PREFIX(16) +struct Mat43V +{ + Mat43V() + { + } + Mat43V(const Vec4V& c0, const Vec4V& c1, const Vec4V& c2) : col0(c0), col1(c1), col2(c2) + { + } + Vec4V PX_ALIGN(16, col0); + Vec4V PX_ALIGN(16, col1); + Vec4V PX_ALIGN(16, col2); +} PX_ALIGN_SUFFIX(16); + +PX_ALIGN_PREFIX(16) +struct Mat44V +{ + Mat44V() + { + } + Mat44V(const Vec4V& c0, const Vec4V& c1, const Vec4V& c2, const Vec4V& c3) : col0(c0), col1(c1), col2(c2), col3(c3) + { + } + Vec4V PX_ALIGN(16, col0); + Vec4V PX_ALIGN(16, col1); + Vec4V PX_ALIGN(16, col2); + Vec4V PX_ALIGN(16, col3); +} PX_ALIGN_SUFFIX(16); + +} // namespace aos +} // namespace shdfnd +} // namespace physx + +#endif // PSFOUNDATION_PSUNIXNEONAOS_H diff --git a/sources/PhysX/PhysX/source/foundation/include/unix/neon/PsUnixNeonInlineAoS.h b/sources/PhysX/PhysX/source/foundation/include/unix/neon/PsUnixNeonInlineAoS.h new file mode 100644 index 00000000..962bfa7a --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/unix/neon/PsUnixNeonInlineAoS.h @@ -0,0 +1,3682 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSUNIXNEONINLINEAOS_H +#define PSFOUNDATION_PSUNIXNEONINLINEAOS_H + +#if !COMPILE_VECTOR_INTRINSICS +#error Vector intrinsics should not be included when using scalar implementation. +#endif + +namespace physx +{ +namespace shdfnd +{ +namespace aos +{ + +// improved estimates +#define VRECIPEQ recipq_newton<1> +#define VRECIPE recip_newton<1> +#define VRECIPSQRTEQ rsqrtq_newton<1> +#define VRECIPSQRTE rsqrt_newton<1> + +// "exact" +#define VRECIPQ recipq_newton<4> +#if PX_SWITCH +// StabilizationTests.AveragePoint needs more precision to succeed. +#define VRECIP recip_newton<5> +#else +#define VRECIP recip_newton<4> +#endif +#define VRECIPSQRTQ rsqrtq_newton<4> +#define VRECIPSQRT rsqrt_newton<4> + +#define VECMATH_AOS_EPSILON (1e-3f) + +////////////////////////////////////////////////////////////////////// +//Test that Vec3V and FloatV are legal +////////////////////////////////// + +#define FLOAT_COMPONENTS_EQUAL_THRESHOLD 0.01f +PX_FORCE_INLINE bool isValidFloatV(const FloatV a) +{ + /* + PX_ALIGN(16, PxF32) data[4]; + vst1_f32(reinterpret_cast(data), a); + return + PxU32* intData = reinterpret_cast(data); + return intData[0] == intData[1]; + */ + PX_ALIGN(16, PxF32) data[4]; + vst1_f32(reinterpret_cast(data), a); + const float32_t x = data[0]; + const float32_t y = data[1]; + + if (PxAbs(x - y) < FLOAT_COMPONENTS_EQUAL_THRESHOLD) + { + return true; + } + + if (PxAbs((x - y) / x) < FLOAT_COMPONENTS_EQUAL_THRESHOLD) + { + return true; + } + + return false; +} + +PX_FORCE_INLINE bool isValidVec3V(const Vec3V a) +{ + const float32_t w = vgetq_lane_f32(a, 3); + return (0.0f == w); + //const PxU32* intData = reinterpret_cast(&w); + //return *intData == 0; +} + +PX_FORCE_INLINE bool isAligned16(const void* a) +{ + return(0 == (size_t(a) & 0x0f)); +} + +#if PX_DEBUG +#define ASSERT_ISVALIDVEC3V(a) PX_ASSERT(isValidVec3V(a)) +#define ASSERT_ISVALIDFLOATV(a) PX_ASSERT(isValidFloatV(a)) +#define ASSERT_ISALIGNED16(a) PX_ASSERT(isAligned16(static_cast(a))) +#else +#define ASSERT_ISVALIDVEC3V(a) +#define ASSERT_ISVALIDFLOATV(a) +#define ASSERT_ISALIGNED16(a) +#endif + +namespace internalUnitNeonSimd +{ +PX_FORCE_INLINE PxU32 BAllTrue4_R(const BoolV a) +{ + const uint16x4_t dHigh = vget_high_u16(vreinterpretq_u16_u32(a)); + const uint16x4_t dLow = vmovn_u32(a); + const uint16x8_t combined = vcombine_u16(dLow, dHigh); + const uint32x2_t finalReduce = vreinterpret_u32_u8(vmovn_u16(combined)); + return PxU32(vget_lane_u32(finalReduce, 0) == 0xffffFFFF); +} + +PX_FORCE_INLINE PxU32 BAllTrue3_R(const BoolV a) +{ + const uint16x4_t dHigh = vget_high_u16(vreinterpretq_u16_u32(a)); + const uint16x4_t dLow = vmovn_u32(a); + const uint16x8_t combined = vcombine_u16(dLow, dHigh); + const uint32x2_t finalReduce = vreinterpret_u32_u8(vmovn_u16(combined)); + return PxU32((vget_lane_u32(finalReduce, 0) & 0xffFFff) == 0xffFFff); +} + +PX_FORCE_INLINE PxU32 BAnyTrue4_R(const BoolV a) +{ + const uint16x4_t dHigh = vget_high_u16(vreinterpretq_u16_u32(a)); + const uint16x4_t dLow = vmovn_u32(a); + const uint16x8_t combined = vcombine_u16(dLow, dHigh); + const uint32x2_t finalReduce = vreinterpret_u32_u8(vmovn_u16(combined)); + return PxU32(vget_lane_u32(finalReduce, 0) != 0x0); +} + +PX_FORCE_INLINE PxU32 BAnyTrue3_R(const BoolV a) +{ + const uint16x4_t dHigh = vget_high_u16(vreinterpretq_u16_u32(a)); + const uint16x4_t dLow = vmovn_u32(a); + const uint16x8_t combined = vcombine_u16(dLow, dHigh); + const uint32x2_t finalReduce = vreinterpret_u32_u8(vmovn_u16(combined)); + return PxU32((vget_lane_u32(finalReduce, 0) & 0xffFFff) != 0); +} +} + +namespace _VecMathTests +{ +// PT: this function returns an invalid Vec3V (W!=0.0f) just for unit-testing 'isValidVec3V' +PX_FORCE_INLINE Vec3V getInvalidVec3V() +{ + PX_ALIGN(16, PxF32) data[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + return V4LoadA(data); +} + +PX_FORCE_INLINE bool allElementsEqualFloatV(const FloatV a, const FloatV b) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(b); + return vget_lane_u32(vceq_f32(a, b), 0) != 0; +} + +PX_FORCE_INLINE bool allElementsEqualVec3V(const Vec3V a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + return V3AllEq(a, b) != 0; +} + +PX_FORCE_INLINE bool allElementsEqualVec4V(const Vec4V a, const Vec4V b) +{ + return V4AllEq(a, b) != 0; +} + +PX_FORCE_INLINE bool allElementsEqualBoolV(const BoolV a, const BoolV b) +{ + return internalUnitNeonSimd::BAllTrue4_R(vceqq_u32(a, b)) != 0; +} + +PX_FORCE_INLINE PxU32 V4U32AllEq(const VecU32V a, const VecU32V b) +{ + return internalUnitNeonSimd::BAllTrue4_R(V4IsEqU32(a, b)); +} + +PX_FORCE_INLINE bool allElementsEqualVecU32V(const VecU32V a, const VecU32V b) +{ + return V4U32AllEq(a, b) != 0; +} + +PX_FORCE_INLINE BoolV V4IsEqI32(const VecI32V a, const VecI32V b) +{ + return vceqq_s32(a, b); +} + +PX_FORCE_INLINE PxU32 V4I32AllEq(const VecI32V a, const VecI32V b) +{ + return internalUnitNeonSimd::BAllTrue4_R(V4IsEqI32(a, b)); +} + +PX_FORCE_INLINE bool allElementsEqualVecI32V(const VecI32V a, const VecI32V b) +{ + return V4I32AllEq(a, b) != 0; +} + +PX_FORCE_INLINE bool allElementsNearEqualFloatV(const FloatV a, const FloatV b) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(b); + + const float32x2_t c = vsub_f32(a, b); + const float32x2_t error = vdup_n_f32(VECMATH_AOS_EPSILON); +// absolute compare abs(error) > abs(c) +#if PX_UWP + const uint32x2_t greater = vacgt_f32(error, c); +#else + const uint32x2_t greater = vcagt_f32(error, c); +#endif + const uint32x2_t min = vpmin_u32(greater, greater); + return vget_lane_u32(min, 0) != 0x0; +} + +PX_FORCE_INLINE bool allElementsNearEqualVec3V(const Vec3V a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + const float32x4_t c = vsubq_f32(a, b); + const float32x4_t error = vdupq_n_f32(VECMATH_AOS_EPSILON); +// absolute compare abs(error) > abs(c) +#if PX_UWP + const uint32x4_t greater = vacgtq_f32(error, c); +#else + const uint32x4_t greater = vcagtq_f32(error, c); +#endif + return internalUnitNeonSimd::BAllTrue3_R(greater) != 0; +} + +PX_FORCE_INLINE bool allElementsNearEqualVec4V(const Vec4V a, const Vec4V b) +{ + const float32x4_t c = vsubq_f32(a, b); + const float32x4_t error = vdupq_n_f32(VECMATH_AOS_EPSILON); +// absolute compare abs(error) > abs(c) +#if PX_UWP + const uint32x4_t greater = vacgtq_f32(error, c); +#else + const uint32x4_t greater = vcagtq_f32(error, c); +#endif + return internalUnitNeonSimd::BAllTrue4_R(greater) != 0x0; +} +} + +#if 0 // debugging printfs +#include +PX_FORCE_INLINE void printVec(const float32x4_t& v, const char* name) +{ + PX_ALIGN(16, float32_t) data[4]; + vst1q_f32(data, v); + printf("%s: (%f, %f, %f, %f)\n", name, data[0], data[1], data[2], data[3]); +} + +PX_FORCE_INLINE void printVec(const float32x2_t& v, const char* name) +{ + PX_ALIGN(16, float32_t) data[2]; + vst1_f32(data, v); + printf("%s: (%f, %f)\n", name, data[0], data[1]); +} + +PX_FORCE_INLINE void printVec(const uint32x4_t& v, const char* name) +{ + PX_ALIGN(16, uint32_t) data[4]; + vst1q_u32(data, v); + printf("%s: (0x%x, 0x%x, 0x%x, 0x%x)\n", name, data[0], data[1], data[2], data[3]); +} + +PX_FORCE_INLINE void printVec(const uint16x8_t& v, const char* name) +{ + PX_ALIGN(16, uint16_t) data[8]; + vst1q_u16(data, v); + printf("%s: (0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", name, data[0], data[1], data[2], data[3], + data[4], data[5], data[6], data[7]); +} + +PX_FORCE_INLINE void printVec(const int32x4_t& v, const char* name) +{ + PX_ALIGN(16, int32_t) data[4]; + vst1q_s32(data, v); + printf("%s: (0x%x, 0x%x, 0x%x, 0x%x)\n", name, data[0], data[1], data[2], data[3]); +} + +PX_FORCE_INLINE void printVec(const int16x8_t& v, const char* name) +{ + PX_ALIGN(16, int16_t) data[8]; + vst1q_s16(data, v); + printf("%s: (0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", name, data[0], data[1], data[2], data[3], + data[4], data[5], data[6], data[7]); +} + +PX_FORCE_INLINE void printVec(const uint16x4_t& v, const char* name) +{ + PX_ALIGN(16, uint16_t) data[4]; + vst1_u16(data, v); + printf("%s: (0x%x, 0x%x, 0x%x, 0x%x)\n", name, data[0], data[1], data[2], data[3]); +} + +PX_FORCE_INLINE void printVec(const uint32x2_t& v, const char* name) +{ + PX_ALIGN(16, uint32_t) data[2]; + vst1_u32(data, v); + printf("%s: (0x%x, 0x%x)\n", name, data[0], data[1]); +} + +PX_FORCE_INLINE void printVar(const PxU32 v, const char* name) +{ + printf("%s: 0x%x\n", name, v); +} + +PX_FORCE_INLINE void printVar(const PxF32 v, const char* name) +{ + printf("%s: %f\n", name, v); +} + +#define PRINT_VAR(X) printVar((X), #X) +#define PRINT_VEC(X) printVec((X), #X) +#define PRINT_VEC_TITLE(TITLE, X) printVec((X), TITLE #X) +#endif // debugging printf + +///////////////////////////////////////////////////////////////////// +////FUNCTIONS USED ONLY FOR ASSERTS IN VECTORISED IMPLEMENTATIONS +///////////////////////////////////////////////////////////////////// + +PX_FORCE_INLINE bool isFiniteFloatV(const FloatV a) +{ + PX_ALIGN(16, PxF32) data[4]; + vst1_f32(reinterpret_cast(data), a); + return PxIsFinite(data[0]) && PxIsFinite(data[1]); +} + +PX_FORCE_INLINE bool isFiniteVec3V(const Vec3V a) +{ + PX_ALIGN(16, PxF32) data[4]; + vst1q_f32(reinterpret_cast(data), a); + return PxIsFinite(data[0]) && PxIsFinite(data[1]) && PxIsFinite(data[2]); +} + +PX_FORCE_INLINE bool isFiniteVec4V(const Vec4V a) +{ + PX_ALIGN(16, PxF32) data[4]; + vst1q_f32(reinterpret_cast(data), a); + return PxIsFinite(data[0]) && PxIsFinite(data[1]) && PxIsFinite(data[2]) && PxIsFinite(data[3]); +} + +PX_FORCE_INLINE bool hasZeroElementinFloatV(const FloatV a) +{ + ASSERT_ISVALIDFLOATV(a); + return vget_lane_u32(vreinterpret_u32_f32(a), 0) == 0; +} + +PX_FORCE_INLINE bool hasZeroElementInVec3V(const Vec3V a) +{ + const uint32x2_t dLow = vget_low_u32(vreinterpretq_u32_f32(a)); + const uint32x2_t dMin = vpmin_u32(dLow, dLow); + + return vget_lane_u32(dMin, 0) == 0 || vgetq_lane_u32(vreinterpretq_u32_f32(a), 2) == 0; +} + +PX_FORCE_INLINE bool hasZeroElementInVec4V(const Vec4V a) +{ + const uint32x2_t dHigh = vget_high_u32(vreinterpretq_u32_f32(a)); + const uint32x2_t dLow = vget_low_u32(vreinterpretq_u32_f32(a)); + + const uint32x2_t dMin = vmin_u32(dHigh, dLow); + const uint32x2_t pairMin = vpmin_u32(dMin, dMin); + return vget_lane_u32(pairMin, 0) == 0; +} + +///////////////////////////////////////////////////////////////////// +////VECTORISED FUNCTION IMPLEMENTATIONS +///////////////////////////////////////////////////////////////////// + +PX_FORCE_INLINE FloatV FLoad(const PxF32 f) +{ + return vdup_n_f32(reinterpret_cast(f)); +} + +PX_FORCE_INLINE FloatV FLoadA(const PxF32* const f) +{ + ASSERT_ISALIGNED16(f); + return vld1_f32(reinterpret_cast(f)); +} + +PX_FORCE_INLINE Vec3V V3Load(const PxF32 f) +{ + PX_ALIGN(16, PxF32) data[4] = { f, f, f, 0.0f }; + return V4LoadA(data); +} + +PX_FORCE_INLINE Vec4V V4Load(const PxF32 f) +{ + return vdupq_n_f32(reinterpret_cast(f)); +} + +PX_FORCE_INLINE BoolV BLoad(const bool f) +{ + const PxU32 i = static_cast(-(static_cast(f))); + return vdupq_n_u32(i); +} + +PX_FORCE_INLINE Vec3V V3LoadA(const PxVec3& f) +{ + ASSERT_ISALIGNED16(&f); + PX_ALIGN(16, PxF32) data[4] = { f.x, f.y, f.z, 0.0f }; + return V4LoadA(data); +} + +PX_FORCE_INLINE Vec3V V3LoadU(const PxVec3& f) +{ + PX_ALIGN(16, PxF32) data[4] = { f.x, f.y, f.z, 0.0f }; + return V4LoadA(data); +} + +PX_FORCE_INLINE Vec3V V3LoadUnsafeA(const PxVec3& f) +{ + ASSERT_ISALIGNED16(&f); + PX_ALIGN(16, PxF32) data[4] = { f.x, f.y, f.z, 0.0f }; + return V4LoadA(data); +} + +PX_FORCE_INLINE Vec3V V3LoadA(const PxF32* f) +{ + ASSERT_ISALIGNED16(f); + PX_ALIGN(16, PxF32) data[4] = { f[0], f[1], f[2], 0.0f }; + return V4LoadA(data); +} + +PX_FORCE_INLINE Vec3V V3LoadU(const PxF32* f) +{ + PX_ALIGN(16, PxF32) data[4] = { f[0], f[1], f[2], 0.0f }; + return V4LoadA(data); +} + +PX_FORCE_INLINE Vec3V Vec3V_From_Vec4V(Vec4V v) +{ + return vsetq_lane_f32(0.0f, v, 3); +} + +PX_FORCE_INLINE Vec3V Vec3V_From_Vec4V_WUndefined(Vec4V v) +{ + return v; +} + +PX_FORCE_INLINE Vec4V Vec4V_From_Vec3V(Vec3V f) +{ + return f; // ok if it is implemented as the same type. +} + +PX_FORCE_INLINE Vec4V Vec4V_From_FloatV(FloatV f) +{ + return vcombine_f32(f, f); +} + +PX_FORCE_INLINE Vec3V Vec3V_From_FloatV(FloatV f) +{ + return Vec3V_From_Vec4V(Vec4V_From_FloatV(f)); +} + +PX_FORCE_INLINE Vec3V Vec3V_From_FloatV_WUndefined(FloatV f) +{ + return Vec3V_From_Vec4V_WUndefined(Vec4V_From_FloatV(f)); +} + +PX_FORCE_INLINE Vec4V Vec4V_From_PxVec3_WUndefined(const PxVec3& f) +{ + PX_ALIGN(16, PxF32) data[4] = { f.x, f.y, f.z, 0.0f }; + return V4LoadA(data); +} + +PX_FORCE_INLINE Mat33V Mat33V_From_PxMat33(const PxMat33& m) +{ + return Mat33V(V3LoadU(m.column0), V3LoadU(m.column1), V3LoadU(m.column2)); +} + +PX_FORCE_INLINE void PxMat33_From_Mat33V(const Mat33V& m, PxMat33& out) +{ + V3StoreU(m.col0, out.column0); + V3StoreU(m.col1, out.column1); + V3StoreU(m.col2, out.column2); +} + +PX_FORCE_INLINE Vec4V V4LoadA(const PxF32* const f) +{ + ASSERT_ISALIGNED16(f); + return vld1q_f32(reinterpret_cast(f)); +} + +PX_FORCE_INLINE void V4StoreA(Vec4V a, PxF32* f) +{ + ASSERT_ISALIGNED16(f); + vst1q_f32(reinterpret_cast(f), a); +} + +PX_FORCE_INLINE void V4StoreU(const Vec4V a, PxF32* f) +{ + PX_ALIGN(16, PxF32) f2[4]; + vst1q_f32(reinterpret_cast(f2), a); + f[0] = f2[0]; + f[1] = f2[1]; + f[2] = f2[2]; + f[3] = f2[3]; +} + +PX_FORCE_INLINE void BStoreA(const BoolV a, PxU32* u) +{ + ASSERT_ISALIGNED16(u); + vst1q_u32(reinterpret_cast(u), a); +} + +PX_FORCE_INLINE void U4StoreA(const VecU32V uv, PxU32* u) +{ + ASSERT_ISALIGNED16(u); + vst1q_u32(reinterpret_cast(u), uv); +} + +PX_FORCE_INLINE void I4StoreA(const VecI32V iv, PxI32* i) +{ + ASSERT_ISALIGNED16(i); + vst1q_s32(reinterpret_cast(i), iv); +} + +PX_FORCE_INLINE Vec4V V4LoadU(const PxF32* const f) +{ + return vld1q_f32(reinterpret_cast(f)); +} + +PX_FORCE_INLINE BoolV BLoad(const bool* const f) +{ + const PX_ALIGN(16, PxU32) b[4] = { static_cast(-static_cast(f[0])), + static_cast(-static_cast(f[1])), + static_cast(-static_cast(f[2])), + static_cast(-static_cast(f[3])) }; + return vld1q_u32(b); +} + +PX_FORCE_INLINE void FStore(const FloatV a, PxF32* PX_RESTRICT f) +{ + ASSERT_ISVALIDFLOATV(a); + // vst1q_lane_f32(f, a, 0); // causes vst1 alignment bug + *f = vget_lane_f32(a, 0); +} + +PX_FORCE_INLINE void Store_From_BoolV(const BoolV a, PxU32* PX_RESTRICT f) +{ + *f = vget_lane_u32(vget_low_u32(a), 0); +} + +PX_FORCE_INLINE void V3StoreA(const Vec3V a, PxVec3& f) +{ + ASSERT_ISALIGNED16(&f); + PX_ALIGN(16, PxF32) f2[4]; + vst1q_f32(reinterpret_cast(f2), a); + f = PxVec3(f2[0], f2[1], f2[2]); +} + +PX_FORCE_INLINE void V3StoreU(const Vec3V a, PxVec3& f) +{ + PX_ALIGN(16, PxF32) f2[4]; + vst1q_f32(reinterpret_cast(f2), a); + f = PxVec3(f2[0], f2[1], f2[2]); +} + +////////////////////////////////// +// FLOATV +////////////////////////////////// + +PX_FORCE_INLINE FloatV FZero() +{ + return FLoad(0.0f); +} + +PX_FORCE_INLINE FloatV FOne() +{ + return FLoad(1.0f); +} + +PX_FORCE_INLINE FloatV FHalf() +{ + return FLoad(0.5f); +} + +PX_FORCE_INLINE FloatV FEps() +{ + return FLoad(PX_EPS_REAL); +} + +PX_FORCE_INLINE FloatV FEps6() +{ + return FLoad(1e-6f); +} + +PX_FORCE_INLINE FloatV FMax() +{ + return FLoad(PX_MAX_REAL); +} + +PX_FORCE_INLINE FloatV FNegMax() +{ + return FLoad(-PX_MAX_REAL); +} + +PX_FORCE_INLINE FloatV IZero() +{ + return vreinterpret_f32_u32(vdup_n_u32(0)); +} + +PX_FORCE_INLINE FloatV IOne() +{ + return vreinterpret_f32_u32(vdup_n_u32(1)); +} + +PX_FORCE_INLINE FloatV ITwo() +{ + return vreinterpret_f32_u32(vdup_n_u32(2)); +} + +PX_FORCE_INLINE FloatV IThree() +{ + return vreinterpret_f32_u32(vdup_n_u32(3)); +} + +PX_FORCE_INLINE FloatV IFour() +{ + return vreinterpret_f32_u32(vdup_n_u32(4)); +} + +PX_FORCE_INLINE FloatV FNeg(const FloatV f) +{ + ASSERT_ISVALIDFLOATV(f); + return vneg_f32(f); +} + +PX_FORCE_INLINE FloatV FAdd(const FloatV a, const FloatV b) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(b); + return vadd_f32(a, b); +} + +PX_FORCE_INLINE FloatV FSub(const FloatV a, const FloatV b) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(b); + return vsub_f32(a, b); +} + +PX_FORCE_INLINE FloatV FMul(const FloatV a, const FloatV b) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(b); + return vmul_f32(a, b); +} + +template +PX_FORCE_INLINE float32x2_t recip_newton(const float32x2_t& in) +{ + float32x2_t recip = vrecpe_f32(in); + for(int i = 0; i < n; ++i) + recip = vmul_f32(recip, vrecps_f32(in, recip)); + return recip; +} + +template +PX_FORCE_INLINE float32x4_t recipq_newton(const float32x4_t& in) +{ + float32x4_t recip = vrecpeq_f32(in); + for(int i = 0; i < n; ++i) + recip = vmulq_f32(recip, vrecpsq_f32(recip, in)); + return recip; +} + +template +PX_FORCE_INLINE float32x2_t rsqrt_newton(const float32x2_t& in) +{ + float32x2_t rsqrt = vrsqrte_f32(in); + for(int i = 0; i < n; ++i) + rsqrt = vmul_f32(rsqrt, vrsqrts_f32(vmul_f32(rsqrt, rsqrt), in)); + return rsqrt; +} + +template +PX_FORCE_INLINE float32x4_t rsqrtq_newton(const float32x4_t& in) +{ + float32x4_t rsqrt = vrsqrteq_f32(in); + for(int i = 0; i < n; ++i) + rsqrt = vmulq_f32(rsqrt, vrsqrtsq_f32(vmulq_f32(rsqrt, rsqrt), in)); + return rsqrt; +} + +PX_FORCE_INLINE FloatV FDiv(const FloatV a, const FloatV b) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(b); + return vmul_f32(a, VRECIP(b)); +} + +PX_FORCE_INLINE FloatV FDivFast(const FloatV a, const FloatV b) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(b); + return vmul_f32(a, VRECIPE(b)); +} + +PX_FORCE_INLINE FloatV FRecip(const FloatV a) +{ + ASSERT_ISVALIDFLOATV(a); + return VRECIP(a); +} + +PX_FORCE_INLINE FloatV FRecipFast(const FloatV a) +{ + ASSERT_ISVALIDFLOATV(a); + return VRECIPE(a); +} + +PX_FORCE_INLINE FloatV FRsqrt(const FloatV a) +{ + ASSERT_ISVALIDFLOATV(a); + return VRECIPSQRT(a); +} + +PX_FORCE_INLINE FloatV FSqrt(const FloatV a) +{ + ASSERT_ISVALIDFLOATV(a); + return FSel(FIsEq(a, FZero()), a, vmul_f32(a, VRECIPSQRT(a))); +} + +PX_FORCE_INLINE FloatV FRsqrtFast(const FloatV a) +{ + ASSERT_ISVALIDFLOATV(a); + return VRECIPSQRTE(a); +} + +PX_FORCE_INLINE FloatV FScaleAdd(const FloatV a, const FloatV b, const FloatV c) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(b); + ASSERT_ISVALIDFLOATV(c); + return vmla_f32(c, a, b); +} + +PX_FORCE_INLINE FloatV FNegScaleSub(const FloatV a, const FloatV b, const FloatV c) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(b); + ASSERT_ISVALIDFLOATV(c); + return vmls_f32(c, a, b); +} + +PX_FORCE_INLINE FloatV FAbs(const FloatV a) +{ + ASSERT_ISVALIDFLOATV(a); + return vabs_f32(a); +} + +PX_FORCE_INLINE FloatV FSel(const BoolV c, const FloatV a, const FloatV b) +{ + PX_ASSERT( _VecMathTests::allElementsEqualBoolV(c, BTTTT()) || + _VecMathTests::allElementsEqualBoolV(c, BFFFF())); + ASSERT_ISVALIDFLOATV(vbsl_f32(vget_low_u32(c), a, b)); + return vbsl_f32(vget_low_u32(c), a, b); +} + +PX_FORCE_INLINE BoolV FIsGrtr(const FloatV a, const FloatV b) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(b); + return vdupq_lane_u32(vcgt_f32(a, b), 0); +} + +PX_FORCE_INLINE BoolV FIsGrtrOrEq(const FloatV a, const FloatV b) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(b); + return vdupq_lane_u32(vcge_f32(a, b), 0); +} + +PX_FORCE_INLINE BoolV FIsEq(const FloatV a, const FloatV b) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(b); + return vdupq_lane_u32(vceq_f32(a, b), 0); +} + +PX_FORCE_INLINE FloatV FMax(const FloatV a, const FloatV b) +{ + //ASSERT_ISVALIDFLOATV(a); + //ASSERT_ISVALIDFLOATV(b); + return vmax_f32(a, b); +} + +PX_FORCE_INLINE FloatV FMin(const FloatV a, const FloatV b) +{ + //ASSERT_ISVALIDFLOATV(a); + //ASSERT_ISVALIDFLOATV(b); + return vmin_f32(a, b); +} + +PX_FORCE_INLINE FloatV FClamp(const FloatV a, const FloatV minV, const FloatV maxV) +{ + ASSERT_ISVALIDFLOATV(minV); + ASSERT_ISVALIDFLOATV(maxV); + return vmax_f32(vmin_f32(a, maxV), minV); +} + +PX_FORCE_INLINE PxU32 FAllGrtr(const FloatV a, const FloatV b) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(b); + return vget_lane_u32(vcgt_f32(a, b), 0); +} + +PX_FORCE_INLINE PxU32 FAllGrtrOrEq(const FloatV a, const FloatV b) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(b); + return vget_lane_u32(vcge_f32(a, b), 0); +} + +PX_FORCE_INLINE PxU32 FAllEq(const FloatV a, const FloatV b) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(b); + return vget_lane_u32(vceq_f32(a, b), 0); +} + +PX_FORCE_INLINE FloatV FRound(const FloatV a) +{ + ASSERT_ISVALIDFLOATV(a); + + // truncate(a + (0.5f - sign(a))) + const float32x2_t half = vdup_n_f32(0.5f); + const float32x2_t sign = vcvt_f32_u32((vshr_n_u32(vreinterpret_u32_f32(a), 31))); + const float32x2_t aPlusHalf = vadd_f32(a, half); + const float32x2_t aRound = vsub_f32(aPlusHalf, sign); + int32x2_t tmp = vcvt_s32_f32(aRound); + return vcvt_f32_s32(tmp); +} + +PX_FORCE_INLINE FloatV FSin(const FloatV a) +{ + ASSERT_ISVALIDFLOATV(a); + + // Modulo the range of the given angles such that -XM_2PI <= Angles < XM_2PI + const FloatV recipTwoPi = FLoadA(g_PXReciprocalTwoPi.f); + const FloatV twoPi = FLoadA(g_PXTwoPi.f); + const FloatV tmp = FMul(a, recipTwoPi); + const FloatV b = FRound(tmp); + const FloatV V1 = FNegScaleSub(twoPi, b, a); + + // sin(V) ~= V - V^3 / 3! + V^5 / 5! - V^7 / 7! + V^9 / 9! - V^11 / 11! + V^13 / 13! - + // V^15 / 15! + V^17 / 17! - V^19 / 19! + V^21 / 21! - V^23 / 23! (for -PI <= V < PI) + const FloatV V2 = FMul(V1, V1); + const FloatV V3 = FMul(V2, V1); + const FloatV V5 = FMul(V3, V2); + const FloatV V7 = FMul(V5, V2); + const FloatV V9 = FMul(V7, V2); + const FloatV V11 = FMul(V9, V2); + const FloatV V13 = FMul(V11, V2); + const FloatV V15 = FMul(V13, V2); + const FloatV V17 = FMul(V15, V2); + const FloatV V19 = FMul(V17, V2); + const FloatV V21 = FMul(V19, V2); + const FloatV V23 = FMul(V21, V2); + + const Vec4V sinCoefficients0 = V4LoadA(g_PXSinCoefficients0.f); + const Vec4V sinCoefficients1 = V4LoadA(g_PXSinCoefficients1.f); + const Vec4V sinCoefficients2 = V4LoadA(g_PXSinCoefficients2.f); + + const FloatV S1 = V4GetY(sinCoefficients0); + const FloatV S2 = V4GetZ(sinCoefficients0); + const FloatV S3 = V4GetW(sinCoefficients0); + const FloatV S4 = V4GetX(sinCoefficients1); + const FloatV S5 = V4GetY(sinCoefficients1); + const FloatV S6 = V4GetZ(sinCoefficients1); + const FloatV S7 = V4GetW(sinCoefficients1); + const FloatV S8 = V4GetX(sinCoefficients2); + const FloatV S9 = V4GetY(sinCoefficients2); + const FloatV S10 = V4GetZ(sinCoefficients2); + const FloatV S11 = V4GetW(sinCoefficients2); + + FloatV Result; + Result = FScaleAdd(S1, V3, V1); + Result = FScaleAdd(S2, V5, Result); + Result = FScaleAdd(S3, V7, Result); + Result = FScaleAdd(S4, V9, Result); + Result = FScaleAdd(S5, V11, Result); + Result = FScaleAdd(S6, V13, Result); + Result = FScaleAdd(S7, V15, Result); + Result = FScaleAdd(S8, V17, Result); + Result = FScaleAdd(S9, V19, Result); + Result = FScaleAdd(S10, V21, Result); + Result = FScaleAdd(S11, V23, Result); + + return Result; +} + +PX_FORCE_INLINE FloatV FCos(const FloatV a) +{ + ASSERT_ISVALIDFLOATV(a); + + // Modulo the range of the given angles such that -XM_2PI <= Angles < XM_2PI + const FloatV recipTwoPi = FLoadA(g_PXReciprocalTwoPi.f); + const FloatV twoPi = FLoadA(g_PXTwoPi.f); + const FloatV tmp = FMul(a, recipTwoPi); + const FloatV b = FRound(tmp); + const FloatV V1 = FNegScaleSub(twoPi, b, a); + + // cos(V) ~= 1 - V^2 / 2! + V^4 / 4! - V^6 / 6! + V^8 / 8! - V^10 / 10! + V^12 / 12! - + // V^14 / 14! + V^16 / 16! - V^18 / 18! + V^20 / 20! - V^22 / 22! (for -PI <= V < PI) + const FloatV V2 = FMul(V1, V1); + const FloatV V4 = FMul(V2, V2); + const FloatV V6 = FMul(V4, V2); + const FloatV V8 = FMul(V4, V4); + const FloatV V10 = FMul(V6, V4); + const FloatV V12 = FMul(V6, V6); + const FloatV V14 = FMul(V8, V6); + const FloatV V16 = FMul(V8, V8); + const FloatV V18 = FMul(V10, V8); + const FloatV V20 = FMul(V10, V10); + const FloatV V22 = FMul(V12, V10); + + const Vec4V cosCoefficients0 = V4LoadA(g_PXCosCoefficients0.f); + const Vec4V cosCoefficients1 = V4LoadA(g_PXCosCoefficients1.f); + const Vec4V cosCoefficients2 = V4LoadA(g_PXCosCoefficients2.f); + + const FloatV C1 = V4GetY(cosCoefficients0); + const FloatV C2 = V4GetZ(cosCoefficients0); + const FloatV C3 = V4GetW(cosCoefficients0); + const FloatV C4 = V4GetX(cosCoefficients1); + const FloatV C5 = V4GetY(cosCoefficients1); + const FloatV C6 = V4GetZ(cosCoefficients1); + const FloatV C7 = V4GetW(cosCoefficients1); + const FloatV C8 = V4GetX(cosCoefficients2); + const FloatV C9 = V4GetY(cosCoefficients2); + const FloatV C10 = V4GetZ(cosCoefficients2); + const FloatV C11 = V4GetW(cosCoefficients2); + + FloatV Result; + Result = FScaleAdd(C1, V2, FOne()); + Result = FScaleAdd(C2, V4, Result); + Result = FScaleAdd(C3, V6, Result); + Result = FScaleAdd(C4, V8, Result); + Result = FScaleAdd(C5, V10, Result); + Result = FScaleAdd(C6, V12, Result); + Result = FScaleAdd(C7, V14, Result); + Result = FScaleAdd(C8, V16, Result); + Result = FScaleAdd(C9, V18, Result); + Result = FScaleAdd(C10, V20, Result); + Result = FScaleAdd(C11, V22, Result); + + return Result; +} + +PX_FORCE_INLINE PxU32 FOutOfBounds(const FloatV a, const FloatV min, const FloatV max) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(min); + ASSERT_ISVALIDFLOATV(max); + + const BoolV c = BOr(FIsGrtr(a, max), FIsGrtr(min, a)); + return PxU32(!BAllEqFFFF(c)); +} + +PX_FORCE_INLINE PxU32 FInBounds(const FloatV a, const FloatV min, const FloatV max) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(min); + ASSERT_ISVALIDFLOATV(max); + + const BoolV c = BAnd(FIsGrtrOrEq(a, min), FIsGrtrOrEq(max, a)); + return PxU32(BAllEqTTTT(c)); +} + +PX_FORCE_INLINE PxU32 FOutOfBounds(const FloatV a, const FloatV bounds) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(bounds); +#if PX_UWP + const uint32x2_t greater = vacgt_f32(a, bounds); +#else + const uint32x2_t greater = vcagt_f32(a, bounds); +#endif + return vget_lane_u32(greater, 0); +} + +PX_FORCE_INLINE PxU32 FInBounds(const FloatV a, const FloatV bounds) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(bounds); +#if PX_UWP + const uint32x2_t geq = vacge_f32(bounds, a); +#else + const uint32x2_t geq = vcage_f32(bounds, a); +#endif + return vget_lane_u32(geq, 0); +} + +////////////////////////////////// +// VEC3V +////////////////////////////////// + +PX_FORCE_INLINE Vec3V V3Splat(const FloatV f) +{ + ASSERT_ISVALIDFLOATV(f); + +#if PX_UWP + const uint32x2_t mask = { 0x00000000ffffFFFFULL }; +#else + const uint32x2_t mask = { 0xffffFFFF, 0x0 }; +#endif + + const uint32x2_t uHigh = vreinterpret_u32_f32(f); + const float32x2_t dHigh = vreinterpret_f32_u32(vand_u32(uHigh, mask)); + + return vcombine_f32(f, dHigh); +} + +PX_FORCE_INLINE Vec3V V3Merge(const FloatVArg x, const FloatVArg y, const FloatVArg z) +{ + ASSERT_ISVALIDFLOATV(x); + ASSERT_ISVALIDFLOATV(y); + ASSERT_ISVALIDFLOATV(z); + +#if PX_UWP + const uint32x2_t mask = { 0x00000000ffffFFFFULL }; +#else + const uint32x2_t mask = { 0xffffFFFF, 0x0 }; +#endif + + const uint32x2_t dHigh = vand_u32(vreinterpret_u32_f32(z), mask); + const uint32x2_t dLow = vext_u32(vreinterpret_u32_f32(x), vreinterpret_u32_f32(y), 1); + return vreinterpretq_f32_u32(vcombine_u32(dLow, dHigh)); +} + +PX_FORCE_INLINE Vec3V V3UnitX() +{ +#if PX_UWP + const float32x4_t x = { 0x000000003f800000ULL, 0x0ULL}; +#else + const float32x4_t x = { 1.0f, 0.0f, 0.0f, 0.0f }; +#endif + return x; +} + +PX_FORCE_INLINE Vec3V V3UnitY() +{ +#if PX_UWP + const float32x4_t y = { 0x3f80000000000000ULL, 0x0ULL}; +#else + const float32x4_t y = { 0, 1.0f, 0, 0 }; +#endif + return y; +} + +PX_FORCE_INLINE Vec3V V3UnitZ() +{ +#if PX_UWP + const float32x4_t z = { 0x0ULL, 0x000000003f800000ULL }; +#else + const float32x4_t z = { 0, 0, 1.0f, 0 }; +#endif + return z; +} + +PX_FORCE_INLINE FloatV V3GetX(const Vec3V f) +{ + ASSERT_ISVALIDVEC3V(f); + const float32x2_t fLow = vget_low_f32(f); + return vdup_lane_f32(fLow, 0); +} + +PX_FORCE_INLINE FloatV V3GetY(const Vec3V f) +{ + ASSERT_ISVALIDVEC3V(f); + const float32x2_t fLow = vget_low_f32(f); + return vdup_lane_f32(fLow, 1); +} + +PX_FORCE_INLINE FloatV V3GetZ(const Vec3V f) +{ + ASSERT_ISVALIDVEC3V(f); + const float32x2_t fhigh = vget_high_f32(f); + return vdup_lane_f32(fhigh, 0); +} + +PX_FORCE_INLINE Vec3V V3SetX(const Vec3V v, const FloatV f) +{ + ASSERT_ISVALIDVEC3V(v); + ASSERT_ISVALIDFLOATV(f); + return V4Sel(BFTTT(), v, vcombine_f32(f, f)); +} + +PX_FORCE_INLINE Vec3V V3SetY(const Vec3V v, const FloatV f) +{ + ASSERT_ISVALIDVEC3V(v); + ASSERT_ISVALIDFLOATV(f); + return V4Sel(BTFTT(), v, vcombine_f32(f, f)); +} + +PX_FORCE_INLINE Vec3V V3SetZ(const Vec3V v, const FloatV f) +{ + ASSERT_ISVALIDVEC3V(v); + ASSERT_ISVALIDFLOATV(f); + return V4Sel(BTTFT(), v, vcombine_f32(f, f)); +} + +PX_FORCE_INLINE Vec3V V3ColX(const Vec3V a, const Vec3V b, const Vec3V c) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + ASSERT_ISVALIDVEC3V(c); + + const float32x2_t aLow = vget_low_f32(a); + const float32x2_t bLow = vget_low_f32(b); + const float32x2_t cLow = vget_low_f32(c); + const float32x2_t zero = vdup_n_f32(0.0f); + + const float32x2x2_t zipL = vzip_f32(aLow, bLow); + const float32x2x2_t zipH = vzip_f32(cLow, zero); + + return vcombine_f32(zipL.val[0], zipH.val[0]); +} + +PX_FORCE_INLINE Vec3V V3ColY(const Vec3V a, const Vec3V b, const Vec3V c) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + ASSERT_ISVALIDVEC3V(c); + + const float32x2_t aLow = vget_low_f32(a); + const float32x2_t bLow = vget_low_f32(b); + const float32x2_t cLow = vget_low_f32(c); + const float32x2_t zero = vdup_n_f32(0.0f); + + const float32x2x2_t zipL = vzip_f32(aLow, bLow); + const float32x2x2_t zipH = vzip_f32(cLow, zero); + + return vcombine_f32(zipL.val[1], zipH.val[1]); +} + +PX_FORCE_INLINE Vec3V V3ColZ(const Vec3V a, const Vec3V b, const Vec3V c) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + ASSERT_ISVALIDVEC3V(c); + + const float32x2_t aHi = vget_high_f32(a); + const float32x2_t bHi = vget_high_f32(b); + const float32x2_t cHi = vget_high_f32(c); + + const float32x2x2_t zipL = vzip_f32(aHi, bHi); + + return vcombine_f32(zipL.val[0], cHi); +} + +PX_FORCE_INLINE Vec3V V3Zero() +{ + return vdupq_n_f32(0.0f); +} + +PX_FORCE_INLINE Vec3V V3Eps() +{ + return V3Load(PX_EPS_REAL); +} + +PX_FORCE_INLINE Vec3V V3One() +{ + return V3Load(1.0f); +} + +PX_FORCE_INLINE Vec3V V3Neg(const Vec3V f) +{ + ASSERT_ISVALIDVEC3V(f); + const float32x4_t tmp = vnegq_f32(f); + return vsetq_lane_f32(0.0f, tmp, 3); +} + +PX_FORCE_INLINE Vec3V V3Add(const Vec3V a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + return vaddq_f32(a, b); +} + +PX_FORCE_INLINE Vec3V V3Add(const Vec3V a, const FloatV b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDFLOATV(b); + return vaddq_f32(a, Vec3V_From_FloatV(b)); +} + +PX_FORCE_INLINE Vec3V V3Sub(const Vec3V a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + return vsubq_f32(a, b); +} + +PX_FORCE_INLINE Vec3V V3Sub(const Vec3V a, const FloatV b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDFLOATV(b); + return vsubq_f32(a, Vec3V_From_FloatV(b)); +} + +PX_FORCE_INLINE Vec3V V3Scale(const Vec3V a, const FloatV b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDFLOATV(b); + const float32x4_t tmp = vmulq_lane_f32(a, b, 0); + return vsetq_lane_f32(0.0f, tmp, 3); +} + +PX_FORCE_INLINE Vec3V V3Mul(const Vec3V a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + return vmulq_f32(a, b); +} + +PX_FORCE_INLINE Vec3V V3ScaleInv(const Vec3V a, const FloatV b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDFLOATV(b); + const float32x2_t invB = VRECIP(b); + const float32x4_t tmp = vmulq_lane_f32(a, invB, 0); + return vsetq_lane_f32(0.0f, tmp, 3); +} + +PX_FORCE_INLINE Vec3V V3Div(const Vec3V a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + float32x4_t invB = VRECIPQ(b); + invB = vsetq_lane_f32(0.0f, invB, 3); + return vmulq_f32(a, invB); +} + +PX_FORCE_INLINE Vec3V V3ScaleInvFast(const Vec3V a, const FloatV b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDFLOATV(b); + const float32x2_t invB = VRECIPE(b); + const float32x4_t tmp = vmulq_lane_f32(a, invB, 0); + return vsetq_lane_f32(0.0f, tmp, 3); +} + +PX_FORCE_INLINE Vec3V V3DivFast(const Vec3V a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + float32x4_t invB = VRECIPEQ(b); + invB = vsetq_lane_f32(0.0f, invB, 3); + return vmulq_f32(a, invB); +} + +PX_FORCE_INLINE Vec3V V3Recip(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + const float32x4_t recipA = VRECIPQ(a); + return vsetq_lane_f32(0.0f, recipA, 3); +} + +PX_FORCE_INLINE Vec3V V3RecipFast(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + const float32x4_t recipA = VRECIPEQ(a); + return vsetq_lane_f32(0.0f, recipA, 3); +} + +PX_FORCE_INLINE Vec3V V3Rsqrt(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + const float32x4_t rSqrA = VRECIPSQRTQ(a); + return vsetq_lane_f32(0.0f, rSqrA, 3); +} + +PX_FORCE_INLINE Vec3V V3RsqrtFast(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + const float32x4_t rSqrA = VRECIPSQRTEQ(a); + return vsetq_lane_f32(0.0f, rSqrA, 3); +} + +PX_FORCE_INLINE Vec3V V3ScaleAdd(const Vec3V a, const FloatV b, const Vec3V c) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDFLOATV(b); + ASSERT_ISVALIDVEC3V(c); + + float32x4_t tmp = vmlaq_lane_f32(c, a, b, 0); + // using vsetq_lane_f32 resulted in failures, + // probably related to a compiler bug on + // ndk r9d-win32, gcc 4.8, cardhu/shield + + // code with issue + // return vsetq_lane_f32(0.0f, tmp, 3); + + // workaround + float32x2_t w_z = vget_high_f32(tmp); + float32x2_t y_x = vget_low_f32(tmp); + w_z = vset_lane_f32(0.0f, w_z, 1); + return vcombine_f32(y_x, w_z); +} + +PX_FORCE_INLINE Vec3V V3NegScaleSub(const Vec3V a, const FloatV b, const Vec3V c) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDFLOATV(b); + ASSERT_ISVALIDVEC3V(c); + + float32x4_t tmp = vmlsq_lane_f32(c, a, b, 0); + // using vsetq_lane_f32 resulted in failures, + // probably related to a compiler bug on + // ndk r9d-win32, gcc 4.8, cardhu/shield + + // code with issue + // return vsetq_lane_f32(0.0f, tmp, 3); + + // workaround + float32x2_t w_z = vget_high_f32(tmp); + float32x2_t y_x = vget_low_f32(tmp); + w_z = vset_lane_f32(0.0f, w_z, 1); + return vcombine_f32(y_x, w_z); +} + +PX_FORCE_INLINE Vec3V V3MulAdd(const Vec3V a, const Vec3V b, const Vec3V c) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + ASSERT_ISVALIDVEC3V(c); + return vmlaq_f32(c, a, b); +} + +PX_FORCE_INLINE Vec3V V3NegMulSub(const Vec3V a, const Vec3V b, const Vec3V c) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + ASSERT_ISVALIDVEC3V(c); + return vmlsq_f32(c, a, b); +} + +PX_FORCE_INLINE Vec3V V3Abs(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + return vabsq_f32(a); +} + +PX_FORCE_INLINE FloatV V3Dot(const Vec3V a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + + // const uint32x2_t mask = {0xffffFFFF, 0x0}; + const float32x4_t tmp = vmulq_f32(a, b); + + const float32x2_t low = vget_low_f32(tmp); + const float32x2_t high = vget_high_f32(tmp); + // const float32x2_t high = vreinterpret_f32_u32(vand_u32(vreinterpret_u32_f32(high_), mask)); + + const float32x2_t sumTmp = vpadd_f32(low, high); // = {0+z, x+y} + const float32x2_t sum0ZYX = vpadd_f32(sumTmp, sumTmp); // = {x+y+z, x+y+z} + + return sum0ZYX; +} + +PX_FORCE_INLINE Vec3V V3Cross(const Vec3V a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + +#if PX_UWP + const uint32x2_t TF = { 0x00000000ffffFFFFULL }; +#else + const uint32x2_t TF = { 0xffffFFFF, 0x0 }; +#endif + const float32x2_t ay_ax = vget_low_f32(a); // d2 + const float32x2_t aw_az = vget_high_f32(a); // d3 + const float32x2_t by_bx = vget_low_f32(b); // d4 + const float32x2_t bw_bz = vget_high_f32(b); // d5 + // Hi, Lo + const float32x2_t bz_by = vext_f32(by_bx, bw_bz, 1); // bz, by + const float32x2_t az_ay = vext_f32(ay_ax, aw_az, 1); // az, ay + + const float32x2_t azbx = vmul_f32(aw_az, by_bx); // 0, az*bx + const float32x2_t aybz_axby = vmul_f32(ay_ax, bz_by); // ay*bz, ax*by + + const float32x2_t azbxSUBaxbz = vmls_f32(azbx, bw_bz, ay_ax); // 0, az*bx-ax*bz + const float32x2_t aybzSUBazby_axbySUBaybx = vmls_f32(aybz_axby, by_bx, az_ay); // ay*bz-az*by, ax*by-ay*bx + + const float32x2_t retLow = vext_f32(aybzSUBazby_axbySUBaybx, azbxSUBaxbz, 1); // az*bx-ax*bz, ay*bz-az*by + const uint32x2_t retHigh = vand_u32(TF, vreinterpret_u32_f32(aybzSUBazby_axbySUBaybx)); // 0, ax*by-ay*bx + + return vcombine_f32(retLow, vreinterpret_f32_u32(retHigh)); +} + +PX_FORCE_INLINE VecCrossV V3PrepareCross(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + return a; +} + +PX_FORCE_INLINE FloatV V3Length(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + + // const uint32x2_t mask = {0xffffFFFF, 0x0}; + + const float32x4_t tmp = vmulq_f32(a, a); + const float32x2_t low = vget_low_f32(tmp); + const float32x2_t high = vget_high_f32(tmp); + // const float32x2_t high = vreinterpret_f32_u32(vand_u32(vreinterpret_u32_f32(high_), mask)); + + const float32x2_t sumTmp = vpadd_f32(low, high); // = {0+z, x+y} + const float32x2_t sum0ZYX = vpadd_f32(sumTmp, sumTmp); // = {x+y+z, x+y+z} + + return FSqrt(sum0ZYX); +} + +PX_FORCE_INLINE FloatV V3LengthSq(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + return V3Dot(a, a); +} + +PX_FORCE_INLINE Vec3V V3Normalize(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + //PX_ASSERT(!FAllEq(V4LengthSq(a), FZero())); + return V3ScaleInv(a, V3Length(a)); +} + +PX_FORCE_INLINE Vec3V V3NormalizeFast(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + //PX_ASSERT(!FAllEq(V4LengthSq(a), FZero())); + return V3Scale(a, VRECIPSQRTE(V3Dot(a, a))); +} + +PX_FORCE_INLINE Vec3V V3NormalizeSafe(const Vec3V a, const Vec3V unsafeReturnValue) +{ + ASSERT_ISVALIDVEC3V(a); + const FloatV zero = vdup_n_f32(0.0f); + const FloatV length = V3Length(a); + const uint32x4_t isGreaterThanZero = FIsGrtr(length, zero); + return V3Sel(isGreaterThanZero, V3ScaleInv(a, length), unsafeReturnValue); +} + +PX_FORCE_INLINE Vec3V V3Sel(const BoolV c, const Vec3V a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V( vbslq_f32(c, a, b)); + return vbslq_f32(c, a, b); +} + +PX_FORCE_INLINE BoolV V3IsGrtr(const Vec3V a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + return vcgtq_f32(a, b); +} + +PX_FORCE_INLINE BoolV V3IsGrtrOrEq(const Vec3V a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + return vcgeq_f32(a, b); +} + +PX_FORCE_INLINE BoolV V3IsEq(const Vec3V a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + return vceqq_f32(a, b); +} + +PX_FORCE_INLINE Vec3V V3Max(const Vec3V a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + return vmaxq_f32(a, b); +} + +PX_FORCE_INLINE Vec3V V3Min(const Vec3V a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + return vminq_f32(a, b); +} + +PX_FORCE_INLINE FloatV V3ExtractMax(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + + const float32x2_t low = vget_low_f32(a); + const float32x2_t high = vget_high_f32(a); + + const float32x2_t zz = vdup_lane_f32(high, 0); + const float32x2_t max0 = vpmax_f32(zz, low); + const float32x2_t max1 = vpmax_f32(max0, max0); + + return max1; +} + +PX_FORCE_INLINE FloatV V3ExtractMin(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + + const float32x2_t low = vget_low_f32(a); + const float32x2_t high = vget_high_f32(a); + + const float32x2_t zz = vdup_lane_f32(high, 0); + const float32x2_t min0 = vpmin_f32(zz, low); + const float32x2_t min1 = vpmin_f32(min0, min0); + + return min1; +} + +// return (a >= 0.0f) ? 1.0f : -1.0f; +PX_FORCE_INLINE Vec3V V3Sign(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + const Vec3V zero = V3Zero(); + const Vec3V one = V3One(); + const Vec3V none = V3Neg(one); + return V3Sel(V3IsGrtrOrEq(a, zero), one, none); +} + +PX_FORCE_INLINE Vec3V V3Clamp(const Vec3V a, const Vec3V minV, const Vec3V maxV) +{ + ASSERT_ISVALIDVEC3V(minV); + ASSERT_ISVALIDVEC3V(maxV); + return V3Max(V3Min(a, maxV), minV); +} + +PX_FORCE_INLINE PxU32 V3AllGrtr(const Vec3V a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + return internalUnitNeonSimd::BAllTrue3_R(V4IsGrtr(a, b)); +} + +PX_FORCE_INLINE PxU32 V3AllGrtrOrEq(const Vec3V a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + return internalUnitNeonSimd::BAllTrue3_R(V4IsGrtrOrEq(a, b)); +} + +PX_FORCE_INLINE PxU32 V3AllEq(const Vec3V a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + return internalUnitNeonSimd::BAllTrue3_R(V4IsEq(a, b)); +} + +PX_FORCE_INLINE Vec3V V3Round(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + // truncate(a + (0.5f - sign(a))) + const Vec3V half = V3Load(0.5f); + const float32x4_t sign = vcvtq_f32_u32((vshrq_n_u32(vreinterpretq_u32_f32(a), 31))); + const Vec3V aPlusHalf = V3Add(a, half); + const Vec3V aRound = V3Sub(aPlusHalf, sign); + return vcvtq_f32_s32(vcvtq_s32_f32(aRound)); +} + +PX_FORCE_INLINE Vec3V V3Sin(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + + // Modulo the range of the given angles such that -XM_2PI <= Angles < XM_2PI + const Vec4V recipTwoPi = V4LoadA(g_PXReciprocalTwoPi.f); + const Vec4V twoPi = V4LoadA(g_PXTwoPi.f); + const Vec3V tmp = V4Mul(a, recipTwoPi); + const Vec3V b = V3Round(tmp); + const Vec3V V1 = V4NegMulSub(twoPi, b, a); + + // sin(V) ~= V - V^3 / 3! + V^5 / 5! - V^7 / 7! + V^9 / 9! - V^11 / 11! + V^13 / 13! - + // V^15 / 15! + V^17 / 17! - V^19 / 19! + V^21 / 21! - V^23 / 23! (for -PI <= V < PI) + const Vec3V V2 = V3Mul(V1, V1); + const Vec3V V3 = V3Mul(V2, V1); + const Vec3V V5 = V3Mul(V3, V2); + const Vec3V V7 = V3Mul(V5, V2); + const Vec3V V9 = V3Mul(V7, V2); + const Vec3V V11 = V3Mul(V9, V2); + const Vec3V V13 = V3Mul(V11, V2); + const Vec3V V15 = V3Mul(V13, V2); + const Vec3V V17 = V3Mul(V15, V2); + const Vec3V V19 = V3Mul(V17, V2); + const Vec3V V21 = V3Mul(V19, V2); + const Vec3V V23 = V3Mul(V21, V2); + + const Vec4V sinCoefficients0 = V4LoadA(g_PXSinCoefficients0.f); + const Vec4V sinCoefficients1 = V4LoadA(g_PXSinCoefficients1.f); + const Vec4V sinCoefficients2 = V4LoadA(g_PXSinCoefficients2.f); + + const FloatV S1 = V4GetY(sinCoefficients0); + const FloatV S2 = V4GetZ(sinCoefficients0); + const FloatV S3 = V4GetW(sinCoefficients0); + const FloatV S4 = V4GetX(sinCoefficients1); + const FloatV S5 = V4GetY(sinCoefficients1); + const FloatV S6 = V4GetZ(sinCoefficients1); + const FloatV S7 = V4GetW(sinCoefficients1); + const FloatV S8 = V4GetX(sinCoefficients2); + const FloatV S9 = V4GetY(sinCoefficients2); + const FloatV S10 = V4GetZ(sinCoefficients2); + const FloatV S11 = V4GetW(sinCoefficients2); + + Vec3V Result; + Result = V4ScaleAdd(V3, S1, V1); + Result = V4ScaleAdd(V5, S2, Result); + Result = V4ScaleAdd(V7, S3, Result); + Result = V4ScaleAdd(V9, S4, Result); + Result = V4ScaleAdd(V11, S5, Result); + Result = V4ScaleAdd(V13, S6, Result); + Result = V4ScaleAdd(V15, S7, Result); + Result = V4ScaleAdd(V17, S8, Result); + Result = V4ScaleAdd(V19, S9, Result); + Result = V4ScaleAdd(V21, S10, Result); + Result = V4ScaleAdd(V23, S11, Result); + + return Result; +} + +PX_FORCE_INLINE Vec3V V3Cos(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + + // Modulo the range of the given angles such that -XM_2PI <= Angles < XM_2PI + const Vec4V recipTwoPi = V4LoadA(g_PXReciprocalTwoPi.f); + const Vec4V twoPi = V4LoadA(g_PXTwoPi.f); + const Vec3V tmp = V4Mul(a, recipTwoPi); + const Vec3V b = V3Round(tmp); + const Vec3V V1 = V4NegMulSub(twoPi, b, a); + + // cos(V) ~= 1 - V^2 / 2! + V^4 / 4! - V^6 / 6! + V^8 / 8! - V^10 / 10! + V^12 / 12! - + // V^14 / 14! + V^16 / 16! - V^18 / 18! + V^20 / 20! - V^22 / 22! (for -PI <= V < PI) + const Vec3V V2 = V3Mul(V1, V1); + const Vec3V V4 = V3Mul(V2, V2); + const Vec3V V6 = V3Mul(V4, V2); + const Vec3V V8 = V3Mul(V4, V4); + const Vec3V V10 = V3Mul(V6, V4); + const Vec3V V12 = V3Mul(V6, V6); + const Vec3V V14 = V3Mul(V8, V6); + const Vec3V V16 = V3Mul(V8, V8); + const Vec3V V18 = V3Mul(V10, V8); + const Vec3V V20 = V3Mul(V10, V10); + const Vec3V V22 = V3Mul(V12, V10); + + const Vec4V cosCoefficients0 = V4LoadA(g_PXCosCoefficients0.f); + const Vec4V cosCoefficients1 = V4LoadA(g_PXCosCoefficients1.f); + const Vec4V cosCoefficients2 = V4LoadA(g_PXCosCoefficients2.f); + + const FloatV C1 = V4GetY(cosCoefficients0); + const FloatV C2 = V4GetZ(cosCoefficients0); + const FloatV C3 = V4GetW(cosCoefficients0); + const FloatV C4 = V4GetX(cosCoefficients1); + const FloatV C5 = V4GetY(cosCoefficients1); + const FloatV C6 = V4GetZ(cosCoefficients1); + const FloatV C7 = V4GetW(cosCoefficients1); + const FloatV C8 = V4GetX(cosCoefficients2); + const FloatV C9 = V4GetY(cosCoefficients2); + const FloatV C10 = V4GetZ(cosCoefficients2); + const FloatV C11 = V4GetW(cosCoefficients2); + + Vec3V Result; + Result = V4ScaleAdd(V2, C1, V4One()); + Result = V4ScaleAdd(V4, C2, Result); + Result = V4ScaleAdd(V6, C3, Result); + Result = V4ScaleAdd(V8, C4, Result); + Result = V4ScaleAdd(V10, C5, Result); + Result = V4ScaleAdd(V12, C6, Result); + Result = V4ScaleAdd(V14, C7, Result); + Result = V4ScaleAdd(V16, C8, Result); + Result = V4ScaleAdd(V18, C9, Result); + Result = V4ScaleAdd(V20, C10, Result); + Result = V4ScaleAdd(V22, C11, Result); + + return V4ClearW(Result); +} + +PX_FORCE_INLINE Vec3V V3PermYZZ(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + const float32x2_t xy = vget_low_f32(a); + const float32x2_t zw = vget_high_f32(a); + const float32x2_t yz = vext_f32(xy, zw, 1); + return vcombine_f32(yz, zw); +} + +PX_FORCE_INLINE Vec3V V3PermXYX(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); +#if PX_UWP + const uint32x2_t mask = { 0x00000000ffffFFFFULL }; +#else + const uint32x2_t mask = { 0xffffFFFF, 0x0 }; +#endif + + const uint32x2_t xy = vget_low_u32(vreinterpretq_u32_f32(a)); + const uint32x2_t xw = vand_u32(xy, mask); + return vreinterpretq_f32_u32(vcombine_u32(xy, xw)); +} + +PX_FORCE_INLINE Vec3V V3PermYZX(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); +#if PX_UWP + const uint32x2_t mask = { 0x00000000ffffFFFFULL }; +#else + const uint32x2_t mask = { 0xffffFFFF, 0x0 }; +#endif + + const uint32x2_t xy = vget_low_u32(vreinterpretq_u32_f32(a)); + const uint32x2_t zw = vget_high_u32(vreinterpretq_u32_f32(a)); + const uint32x2_t yz = vext_u32(xy, zw, 1); + const uint32x2_t xw = vand_u32(xy, mask); + return vreinterpretq_f32_u32(vcombine_u32(yz, xw)); +} + +PX_FORCE_INLINE Vec3V V3PermZXY(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + + const uint32x2_t xy = vget_low_u32(vreinterpretq_u32_f32(a)); + const uint32x2_t zw = vget_high_u32(vreinterpretq_u32_f32(a)); + const uint32x2_t wz = vrev64_u32(zw); + + const uint32x2_t zx = vext_u32(wz, xy, 1); + const uint32x2_t yw = vext_u32(xy, wz, 1); + + return vreinterpretq_f32_u32(vcombine_u32(zx, yw)); +} + +PX_FORCE_INLINE Vec3V V3PermZZY(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + + const uint32x2_t xy = vget_low_u32(vreinterpretq_u32_f32(a)); + const uint32x2_t zw = vget_high_u32(vreinterpretq_u32_f32(a)); + + const uint32x2_t wz = vrev64_u32(zw); + const uint32x2_t yw = vext_u32(xy, wz, 1); + const uint32x2_t zz = vdup_lane_u32(wz, 1); + + return vreinterpretq_f32_u32(vcombine_u32(zz, yw)); +} + +PX_FORCE_INLINE Vec3V V3PermYXX(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + +#if PX_UWP + const uint32x2_t mask = { 0x00000000ffffFFFFULL }; +#else + const uint32x2_t mask = { 0xffffFFFF, 0x0 }; +#endif + + const uint32x2_t xy = vget_low_u32(vreinterpretq_u32_f32(a)); + const uint32x2_t yx = vrev64_u32(xy); + const uint32x2_t xw = vand_u32(xy, mask); + return vreinterpretq_f32_u32(vcombine_u32(yx, xw)); +} + +PX_FORCE_INLINE Vec3V V3Perm_Zero_1Z_0Y(const Vec3V v0, const Vec3V v1) +{ + ASSERT_ISVALIDVEC3V(v0); + ASSERT_ISVALIDVEC3V(v1); + + const uint32x2_t xy = vget_low_u32(vreinterpretq_u32_f32(v0)); + const uint32x2_t zw = vget_high_u32(vreinterpretq_u32_f32(v1)); + const uint32x2_t wz = vrev64_u32(zw); + const uint32x2_t yw = vext_u32(xy, wz, 1); + + return vreinterpretq_f32_u32(vcombine_u32(wz, yw)); +} + +PX_FORCE_INLINE Vec3V V3Perm_0Z_Zero_1X(const Vec3V v0, const Vec3V v1) +{ + ASSERT_ISVALIDVEC3V(v0); + ASSERT_ISVALIDVEC3V(v1); + +#if PX_UWP + const uint32x2_t mask = { 0x00000000ffffFFFFULL }; +#else + const uint32x2_t mask = { 0xffffFFFF, 0x0 }; +#endif + + const uint32x2_t zw = vget_high_u32(vreinterpretq_u32_f32(v0)); + const uint32x2_t xy = vget_low_u32(vreinterpretq_u32_f32(v1)); + const uint32x2_t xw = vand_u32(xy, mask); + + return vreinterpretq_f32_u32(vcombine_u32(zw, xw)); +} + +PX_FORCE_INLINE Vec3V V3Perm_1Y_0X_Zero(const Vec3V v0, const Vec3V v1) +{ + ASSERT_ISVALIDVEC3V(v0); + ASSERT_ISVALIDVEC3V(v1); + + const uint32x2_t axy = vget_low_u32(vreinterpretq_u32_f32(v0)); + const uint32x2_t bxy = vget_low_u32(vreinterpretq_u32_f32(v1)); + const uint32x2_t byax = vext_u32(bxy, axy, 1); + const uint32x2_t ww = vdup_n_u32(0); + + return vreinterpretq_f32_u32(vcombine_u32(byax, ww)); +} + +PX_FORCE_INLINE FloatV V3SumElems(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + + // const uint32x2_t mask = {0xffffFFFF, 0x0}; + + const float32x2_t low = vget_low_f32(a); + const float32x2_t high = vget_high_f32(a); + // const float32x2_t high = vreinterpret_f32_u32(vand_u32(vreinterpret_u32_f32(high_), mask)); + + const float32x2_t sumTmp = vpadd_f32(low, high); // = {0+z, x+y} + const float32x2_t sum0ZYX = vpadd_f32(sumTmp, sumTmp); // = {x+y+z, x+y+z} + + return sum0ZYX; +} + +PX_FORCE_INLINE PxU32 V3OutOfBounds(const Vec3V a, const Vec3V min, const Vec3V max) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(min); + ASSERT_ISVALIDVEC3V(max); + + const BoolV c = BOr(V3IsGrtr(a, max), V3IsGrtr(min, a)); + return internalUnitNeonSimd::BAnyTrue3_R(c); +} + +PX_FORCE_INLINE PxU32 V3InBounds(const Vec3V a, const Vec3V min, const Vec3V max) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(min); + ASSERT_ISVALIDVEC3V(max); + + const BoolV c = BAnd(V3IsGrtrOrEq(a, min), V3IsGrtrOrEq(max, a)); + return internalUnitNeonSimd::BAllTrue4_R(c); +} + +PX_FORCE_INLINE PxU32 V3OutOfBounds(const Vec3V a, const Vec3V bounds) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(bounds); + + const BoolV greater = V3IsGrtr(V3Abs(a), bounds); + return internalUnitNeonSimd::BAnyTrue3_R(greater); +} + +PX_FORCE_INLINE PxU32 V3InBounds(const Vec3V a, const Vec3V bounds) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(bounds); + + const BoolV greaterOrEq = V3IsGrtrOrEq(bounds, V3Abs(a)); + return internalUnitNeonSimd::BAllTrue4_R(greaterOrEq); +} + +PX_FORCE_INLINE void V3Transpose(Vec3V& col0, Vec3V& col1, Vec3V& col2) +{ + ASSERT_ISVALIDVEC3V(col0); + ASSERT_ISVALIDVEC3V(col1); + ASSERT_ISVALIDVEC3V(col2); + + Vec3V col3 = V3Zero(); + const float32x4x2_t v0v1 = vzipq_f32(col0, col2); + const float32x4x2_t v2v3 = vzipq_f32(col1, col3); + const float32x4x2_t zip0 = vzipq_f32(v0v1.val[0], v2v3.val[0]); + const float32x4x2_t zip1 = vzipq_f32(v0v1.val[1], v2v3.val[1]); + col0 = zip0.val[0]; + col1 = zip0.val[1]; + col2 = zip1.val[0]; + // col3 = zip1.val[1]; +} + +////////////////////////////////// +// VEC4V +////////////////////////////////// + +PX_FORCE_INLINE Vec4V V4Splat(const FloatV f) +{ + ASSERT_ISVALIDFLOATV(f); + return vcombine_f32(f, f); +} + +PX_FORCE_INLINE Vec4V V4Merge(const FloatV* const floatVArray) +{ + ASSERT_ISVALIDFLOATV(floatVArray[0]); + ASSERT_ISVALIDFLOATV(floatVArray[1]); + ASSERT_ISVALIDFLOATV(floatVArray[2]); + ASSERT_ISVALIDFLOATV(floatVArray[3]); + + const uint32x2_t xLow = vreinterpret_u32_f32(floatVArray[0]); + const uint32x2_t yLow = vreinterpret_u32_f32(floatVArray[1]); + const uint32x2_t zLow = vreinterpret_u32_f32(floatVArray[2]); + const uint32x2_t wLow = vreinterpret_u32_f32(floatVArray[3]); + + const uint32x2_t dLow = vext_u32(xLow, yLow, 1); + const uint32x2_t dHigh = vext_u32(zLow, wLow, 1); + + return vreinterpretq_f32_u32(vcombine_u32(dLow, dHigh)); +} + +PX_FORCE_INLINE Vec4V V4Merge(const FloatVArg x, const FloatVArg y, const FloatVArg z, const FloatVArg w) +{ + ASSERT_ISVALIDFLOATV(x); + ASSERT_ISVALIDFLOATV(y); + ASSERT_ISVALIDFLOATV(z); + ASSERT_ISVALIDFLOATV(w); + + const uint32x2_t xLow = vreinterpret_u32_f32(x); + const uint32x2_t yLow = vreinterpret_u32_f32(y); + const uint32x2_t zLow = vreinterpret_u32_f32(z); + const uint32x2_t wLow = vreinterpret_u32_f32(w); + + const uint32x2_t dLow = vext_u32(xLow, yLow, 1); + const uint32x2_t dHigh = vext_u32(zLow, wLow, 1); + + return vreinterpretq_f32_u32(vcombine_u32(dLow, dHigh)); +} + +PX_FORCE_INLINE Vec4V V4MergeW(const Vec4VArg x, const Vec4VArg y, const Vec4VArg z, const Vec4VArg w) +{ + const float32x2_t xx = vget_high_f32(x); + const float32x2_t yy = vget_high_f32(y); + const float32x2_t zz = vget_high_f32(z); + const float32x2_t ww = vget_high_f32(w); + + const float32x2x2_t zipL = vzip_f32(xx, yy); + const float32x2x2_t zipH = vzip_f32(zz, ww); + + return vcombine_f32(zipL.val[1], zipH.val[1]); +} + +PX_FORCE_INLINE Vec4V V4MergeZ(const Vec4VArg x, const Vec4VArg y, const Vec4VArg z, const Vec4VArg w) +{ + const float32x2_t xx = vget_high_f32(x); + const float32x2_t yy = vget_high_f32(y); + const float32x2_t zz = vget_high_f32(z); + const float32x2_t ww = vget_high_f32(w); + + const float32x2x2_t zipL = vzip_f32(xx, yy); + const float32x2x2_t zipH = vzip_f32(zz, ww); + + return vcombine_f32(zipL.val[0], zipH.val[0]); +} + +PX_FORCE_INLINE Vec4V V4MergeY(const Vec4VArg x, const Vec4VArg y, const Vec4VArg z, const Vec4VArg w) +{ + const float32x2_t xx = vget_low_f32(x); + const float32x2_t yy = vget_low_f32(y); + const float32x2_t zz = vget_low_f32(z); + const float32x2_t ww = vget_low_f32(w); + + const float32x2x2_t zipL = vzip_f32(xx, yy); + const float32x2x2_t zipH = vzip_f32(zz, ww); + + return vcombine_f32(zipL.val[1], zipH.val[1]); +} + +PX_FORCE_INLINE Vec4V V4MergeX(const Vec4VArg x, const Vec4VArg y, const Vec4VArg z, const Vec4VArg w) +{ + const float32x2_t xx = vget_low_f32(x); + const float32x2_t yy = vget_low_f32(y); + const float32x2_t zz = vget_low_f32(z); + const float32x2_t ww = vget_low_f32(w); + + const float32x2x2_t zipL = vzip_f32(xx, yy); + const float32x2x2_t zipH = vzip_f32(zz, ww); + + return vcombine_f32(zipL.val[0], zipH.val[0]); +} + +PX_FORCE_INLINE Vec4V V4UnpackXY(const Vec4VArg a, const Vec4VArg b) +{ + return vzipq_f32(a, b).val[0]; +} + +PX_FORCE_INLINE Vec4V V4UnpackZW(const Vec4VArg a, const Vec4VArg b) +{ + return vzipq_f32(a, b).val[1]; +} + +PX_FORCE_INLINE Vec4V V4UnitW() +{ + const float32x2_t zeros = vreinterpret_f32_u32(vmov_n_u32(0)); + const float32x2_t ones = vmov_n_f32(1.0f); + const float32x2_t zo = vext_f32(zeros, ones, 1); + return vcombine_f32(zeros, zo); +} + +PX_FORCE_INLINE Vec4V V4UnitX() +{ + const float32x2_t zeros = vreinterpret_f32_u32(vmov_n_u32(0)); + const float32x2_t ones = vmov_n_f32(1.0f); + const float32x2_t oz = vext_f32(ones, zeros, 1); + return vcombine_f32(oz, zeros); +} + +PX_FORCE_INLINE Vec4V V4UnitY() +{ + const float32x2_t zeros = vreinterpret_f32_u32(vmov_n_u32(0)); + const float32x2_t ones = vmov_n_f32(1.0f); + const float32x2_t zo = vext_f32(zeros, ones, 1); + return vcombine_f32(zo, zeros); +} + +PX_FORCE_INLINE Vec4V V4UnitZ() +{ + const float32x2_t zeros = vreinterpret_f32_u32(vmov_n_u32(0)); + const float32x2_t ones = vmov_n_f32(1.0f); + const float32x2_t oz = vext_f32(ones, zeros, 1); + return vcombine_f32(zeros, oz); +} + +PX_FORCE_INLINE FloatV V4GetW(const Vec4V f) +{ + const float32x2_t fhigh = vget_high_f32(f); + return vdup_lane_f32(fhigh, 1); +} + +PX_FORCE_INLINE FloatV V4GetX(const Vec4V f) +{ + const float32x2_t fLow = vget_low_f32(f); + return vdup_lane_f32(fLow, 0); +} + +PX_FORCE_INLINE FloatV V4GetY(const Vec4V f) +{ + const float32x2_t fLow = vget_low_f32(f); + return vdup_lane_f32(fLow, 1); +} + +PX_FORCE_INLINE FloatV V4GetZ(const Vec4V f) +{ + const float32x2_t fhigh = vget_high_f32(f); + return vdup_lane_f32(fhigh, 0); +} + +PX_FORCE_INLINE Vec4V V4SetW(const Vec4V v, const FloatV f) +{ + ASSERT_ISVALIDFLOATV(f); + return V4Sel(BTTTF(), v, vcombine_f32(f, f)); +} + +PX_FORCE_INLINE Vec4V V4SetX(const Vec4V v, const FloatV f) +{ + ASSERT_ISVALIDFLOATV(f); + return V4Sel(BFTTT(), v, vcombine_f32(f, f)); +} + +PX_FORCE_INLINE Vec4V V4SetY(const Vec4V v, const FloatV f) +{ + ASSERT_ISVALIDFLOATV(f); + return V4Sel(BTFTT(), v, vcombine_f32(f, f)); +} + +PX_FORCE_INLINE Vec4V V4SetZ(const Vec4V v, const FloatV f) +{ + ASSERT_ISVALIDFLOATV(f); + return V4Sel(BTTFT(), v, vcombine_f32(f, f)); +} + +PX_FORCE_INLINE Vec4V V4ClearW(const Vec4V v) +{ + return V4Sel(BTTTF(), v, V4Zero()); +} + +PX_FORCE_INLINE Vec4V V4PermYXWZ(const Vec4V a) +{ + const float32x2_t xy = vget_low_f32(a); + const float32x2_t zw = vget_high_f32(a); + const float32x2_t yx = vext_f32(xy, xy, 1); + const float32x2_t wz = vext_f32(zw, zw, 1); + return vcombine_f32(yx, wz); +} + +PX_FORCE_INLINE Vec4V V4PermXZXZ(const Vec4V a) +{ + const float32x2_t xy = vget_low_f32(a); + const float32x2_t zw = vget_high_f32(a); + const float32x2x2_t xzyw = vzip_f32(xy, zw); + return vcombine_f32(xzyw.val[0], xzyw.val[0]); +} + +PX_FORCE_INLINE Vec4V V4PermYWYW(const Vec4V a) +{ + const float32x2_t xy = vget_low_f32(a); + const float32x2_t zw = vget_high_f32(a); + const float32x2x2_t xzyw = vzip_f32(xy, zw); + return vcombine_f32(xzyw.val[1], xzyw.val[1]); +} + +PX_FORCE_INLINE Vec4V V4PermYZXW(const Vec4V a) +{ + const uint32x2_t xy = vget_low_u32(vreinterpretq_u32_f32(a)); + const uint32x2_t zw = vget_high_u32(vreinterpretq_u32_f32(a)); + const uint32x2_t yz = vext_u32(xy, zw, 1); + const uint32x2_t xw = vrev64_u32(vext_u32(zw, xy, 1)); + return vreinterpretq_f32_u32(vcombine_u32(yz, xw)); +} + +PX_FORCE_INLINE Vec4V V4PermZWXY(const Vec4V a) +{ + const float32x2_t low = vget_low_f32(a); + const float32x2_t high = vget_high_f32(a); + return vcombine_f32(high, low); +} + +template +PX_FORCE_INLINE Vec4V V4Perm(const Vec4V V) +{ + static const uint32_t ControlElement[4] = + { +#if 1 + 0x03020100, // XM_SWIZZLE_X + 0x07060504, // XM_SWIZZLE_Y + 0x0B0A0908, // XM_SWIZZLE_Z + 0x0F0E0D0C, // XM_SWIZZLE_W +#else + 0x00010203, // XM_SWIZZLE_X + 0x04050607, // XM_SWIZZLE_Y + 0x08090A0B, // XM_SWIZZLE_Z + 0x0C0D0E0F, // XM_SWIZZLE_W +#endif + }; + + uint8x8x2_t tbl; + tbl.val[0] = vreinterpret_u8_f32(vget_low_f32(V)); + tbl.val[1] = vreinterpret_u8_f32(vget_high_f32(V)); + + uint8x8_t idx = + vcreate_u8(static_cast(ControlElement[E0]) | (static_cast(ControlElement[E1]) << 32)); + const uint8x8_t rL = vtbl2_u8(tbl, idx); + idx = vcreate_u8(static_cast(ControlElement[E2]) | (static_cast(ControlElement[E3]) << 32)); + const uint8x8_t rH = vtbl2_u8(tbl, idx); + return vreinterpretq_f32_u8(vcombine_u8(rL, rH)); +} + +// PT: this seems measurably slower than the hardcoded version +/*PX_FORCE_INLINE Vec4V V4PermYZXW(const Vec4V a) +{ + return V4Perm<1, 2, 0, 3>(a); +}*/ + +PX_FORCE_INLINE Vec4V V4Zero() +{ + return vreinterpretq_f32_u32(vmovq_n_u32(0)); + // return vmovq_n_f32(0.0f); +} + +PX_FORCE_INLINE Vec4V V4One() +{ + return vmovq_n_f32(1.0f); +} + +PX_FORCE_INLINE Vec4V V4Eps() +{ + // return vmovq_n_f32(PX_EPS_REAL); + return V4Load(PX_EPS_REAL); +} + +PX_FORCE_INLINE Vec4V V4Neg(const Vec4V f) +{ + return vnegq_f32(f); +} + +PX_FORCE_INLINE Vec4V V4Add(const Vec4V a, const Vec4V b) +{ + return vaddq_f32(a, b); +} + +PX_FORCE_INLINE Vec4V V4Sub(const Vec4V a, const Vec4V b) +{ + return vsubq_f32(a, b); +} + +PX_FORCE_INLINE Vec4V V4Scale(const Vec4V a, const FloatV b) +{ + return vmulq_lane_f32(a, b, 0); +} + +PX_FORCE_INLINE Vec4V V4Mul(const Vec4V a, const Vec4V b) +{ + return vmulq_f32(a, b); +} + +PX_FORCE_INLINE Vec4V V4ScaleInv(const Vec4V a, const FloatV b) +{ + ASSERT_ISVALIDFLOATV(b); + const float32x2_t invB = VRECIP(b); + return vmulq_lane_f32(a, invB, 0); +} + +PX_FORCE_INLINE Vec4V V4Div(const Vec4V a, const Vec4V b) +{ + const float32x4_t invB = VRECIPQ(b); + return vmulq_f32(a, invB); +} + +PX_FORCE_INLINE Vec4V V4ScaleInvFast(const Vec4V a, const FloatV b) +{ + ASSERT_ISVALIDFLOATV(b); + const float32x2_t invB = VRECIPE(b); + return vmulq_lane_f32(a, invB, 0); +} + +PX_FORCE_INLINE Vec4V V4DivFast(const Vec4V a, const Vec4V b) +{ + const float32x4_t invB = VRECIPEQ(b); + return vmulq_f32(a, invB); +} + +PX_FORCE_INLINE Vec4V V4Recip(const Vec4V a) +{ + return VRECIPQ(a); +} + +PX_FORCE_INLINE Vec4V V4RecipFast(const Vec4V a) +{ + return VRECIPEQ(a); +} + +PX_FORCE_INLINE Vec4V V4Rsqrt(const Vec4V a) +{ + return VRECIPSQRTQ(a); +} + +PX_FORCE_INLINE Vec4V V4RsqrtFast(const Vec4V a) +{ + return VRECIPSQRTEQ(a); +} + +PX_FORCE_INLINE Vec4V V4Sqrt(const Vec4V a) +{ + return V4Sel(V4IsEq(a, V4Zero()), a, V4Mul(a, VRECIPSQRTQ(a))); +} + +PX_FORCE_INLINE Vec4V V4ScaleAdd(const Vec4V a, const FloatV b, const Vec4V c) +{ + ASSERT_ISVALIDFLOATV(b); + return vmlaq_lane_f32(c, a, b, 0); +} + +PX_FORCE_INLINE Vec4V V4NegScaleSub(const Vec4V a, const FloatV b, const Vec4V c) +{ + ASSERT_ISVALIDFLOATV(b); + return vmlsq_lane_f32(c, a, b, 0); +} + +PX_FORCE_INLINE Vec4V V4MulAdd(const Vec4V a, const Vec4V b, const Vec4V c) +{ + return vmlaq_f32(c, a, b); +} + +PX_FORCE_INLINE Vec4V V4NegMulSub(const Vec4V a, const Vec4V b, const Vec4V c) +{ + return vmlsq_f32(c, a, b); +} + +PX_FORCE_INLINE Vec4V V4Abs(const Vec4V a) +{ + return vabsq_f32(a); +} + +PX_FORCE_INLINE FloatV V4SumElements(const Vec4V a) +{ + const Vec4V xy = V4UnpackXY(a, a); // x,x,y,y + const Vec4V zw = V4UnpackZW(a, a); // z,z,w,w + const Vec4V xz_yw = V4Add(xy, zw); // x+z,x+z,y+w,y+w + const FloatV xz = V4GetX(xz_yw); // x+z + const FloatV yw = V4GetZ(xz_yw); // y+w + return FAdd(xz, yw); // sum +} + +PX_FORCE_INLINE FloatV V4Dot(const Vec4V a, const Vec4V b) +{ + const float32x4_t tmp = vmulq_f32(a, b); + const float32x2_t low = vget_low_f32(tmp); + const float32x2_t high = vget_high_f32(tmp); + + const float32x2_t sumTmp = vpadd_f32(low, high); // = {z+w, x+y} + const float32x2_t sumWZYX = vpadd_f32(sumTmp, sumTmp); // = {x+y+z+w, x+y+z+w} + return sumWZYX; +} + +PX_FORCE_INLINE FloatV V4Dot3(const Vec4V aa, const Vec4V bb) +{ + // PT: the V3Dot code relies on the fact that W=0 so we can't reuse it as-is, we need to clear W first. + // TODO: find a better implementation that does not need to clear W. + const Vec4V a = V4ClearW(aa); + const Vec4V b = V4ClearW(bb); + + const float32x4_t tmp = vmulq_f32(a, b); + const float32x2_t low = vget_low_f32(tmp); + const float32x2_t high = vget_high_f32(tmp); + + const float32x2_t sumTmp = vpadd_f32(low, high); // = {0+z, x+y} + const float32x2_t sum0ZYX = vpadd_f32(sumTmp, sumTmp); // = {x+y+z, x+y+z} + return sum0ZYX; +} + +PX_FORCE_INLINE Vec4V V4Cross(const Vec4V a, const Vec4V b) +{ +#if PX_UWP + const uint32x2_t TF = { 0x00000000ffffFFFFULL }; +#else + const uint32x2_t TF = { 0xffffFFFF, 0x0 }; +#endif + const float32x2_t ay_ax = vget_low_f32(a); // d2 + const float32x2_t aw_az = vget_high_f32(a); // d3 + const float32x2_t by_bx = vget_low_f32(b); // d4 + const float32x2_t bw_bz = vget_high_f32(b); // d5 + // Hi, Lo + const float32x2_t bz_by = vext_f32(by_bx, bw_bz, 1); // bz, by + const float32x2_t az_ay = vext_f32(ay_ax, aw_az, 1); // az, ay + + const float32x2_t azbx = vmul_f32(aw_az, by_bx); // 0, az*bx + const float32x2_t aybz_axby = vmul_f32(ay_ax, bz_by); // ay*bz, ax*by + + const float32x2_t azbxSUBaxbz = vmls_f32(azbx, bw_bz, ay_ax); // 0, az*bx-ax*bz + const float32x2_t aybzSUBazby_axbySUBaybx = vmls_f32(aybz_axby, by_bx, az_ay); // ay*bz-az*by, ax*by-ay*bx + + const float32x2_t retLow = vext_f32(aybzSUBazby_axbySUBaybx, azbxSUBaxbz, 1); // az*bx-ax*bz, ay*bz-az*by + const uint32x2_t retHigh = vand_u32(TF, vreinterpret_u32_f32(aybzSUBazby_axbySUBaybx)); // 0, ax*by-ay*bx + + return vcombine_f32(retLow, vreinterpret_f32_u32(retHigh)); +} + +PX_FORCE_INLINE FloatV V4Length(const Vec4V a) +{ + const float32x4_t tmp = vmulq_f32(a, a); + const float32x2_t low = vget_low_f32(tmp); + const float32x2_t high = vget_high_f32(tmp); + + const float32x2_t sumTmp = vpadd_f32(low, high); // = {0+z, x+y} + const float32x2_t sumWZYX = vpadd_f32(sumTmp, sumTmp); // = {x+y+z, x+y+z} + return FSqrt(sumWZYX); +} + +PX_FORCE_INLINE FloatV V4LengthSq(const Vec4V a) +{ + return V4Dot(a, a); +} + +PX_FORCE_INLINE Vec4V V4Normalize(const Vec4V a) +{ + //PX_ASSERT(!FAllEq(V4LengthSq(a), FZero())); + return V4ScaleInv(a, V4Length(a)); +} + +PX_FORCE_INLINE Vec4V V4NormalizeFast(const Vec4V a) +{ + //PX_ASSERT(!FAllEq(V4LengthSq(a), FZero())); + return V4Scale(a, FRsqrtFast(V4Dot(a, a))); +} + +PX_FORCE_INLINE Vec4V V4NormalizeSafe(const Vec4V a, const Vec4V unsafeReturnValue) +{ + const FloatV zero = FZero(); + const FloatV length = V4Length(a); + const uint32x4_t isGreaterThanZero = FIsGrtr(length, zero); + return V4Sel(isGreaterThanZero, V4ScaleInv(a, length), unsafeReturnValue); +} + +PX_FORCE_INLINE BoolV V4IsEqU32(const VecU32V a, const VecU32V b) +{ + return vceqq_u32(a, b); +} + +PX_FORCE_INLINE Vec4V V4Sel(const BoolV c, const Vec4V a, const Vec4V b) +{ + return vbslq_f32(c, a, b); +} + +PX_FORCE_INLINE BoolV V4IsGrtr(const Vec4V a, const Vec4V b) +{ + return vcgtq_f32(a, b); +} + +PX_FORCE_INLINE BoolV V4IsGrtrOrEq(const Vec4V a, const Vec4V b) +{ + return vcgeq_f32(a, b); +} + +PX_FORCE_INLINE BoolV V4IsEq(const Vec4V a, const Vec4V b) +{ + return vceqq_f32(a, b); +} + +PX_FORCE_INLINE Vec4V V4Max(const Vec4V a, const Vec4V b) +{ + return vmaxq_f32(a, b); +} + +PX_FORCE_INLINE Vec4V V4Min(const Vec4V a, const Vec4V b) +{ + return vminq_f32(a, b); +} + +PX_FORCE_INLINE FloatV V4ExtractMax(const Vec4V a) +{ + const float32x2_t low = vget_low_f32(a); + const float32x2_t high = vget_high_f32(a); + + const float32x2_t max0 = vpmax_f32(high, low); + const float32x2_t max1 = vpmax_f32(max0, max0); + + return max1; +} + +PX_FORCE_INLINE FloatV V4ExtractMin(const Vec4V a) +{ + const float32x2_t low = vget_low_f32(a); + const float32x2_t high = vget_high_f32(a); + + const float32x2_t min0 = vpmin_f32(high, low); + const float32x2_t min1 = vpmin_f32(min0, min0); + + return min1; +} + +PX_FORCE_INLINE Vec4V V4Clamp(const Vec4V a, const Vec4V minV, const Vec4V maxV) +{ + return V4Max(V4Min(a, maxV), minV); +} + +PX_FORCE_INLINE PxU32 V4AllGrtr(const Vec4V a, const Vec4V b) +{ + return internalUnitNeonSimd::BAllTrue4_R(V4IsGrtr(a, b)); +} + +PX_FORCE_INLINE PxU32 V4AllGrtrOrEq(const Vec4V a, const Vec4V b) +{ + return internalUnitNeonSimd::BAllTrue4_R(V4IsGrtrOrEq(a, b)); +} + +PX_FORCE_INLINE PxU32 V4AllGrtrOrEq3(const Vec4V a, const Vec4V b) +{ + return internalUnitNeonSimd::BAllTrue3_R(V4IsGrtrOrEq(a, b)); +} + +PX_FORCE_INLINE PxU32 V4AllEq(const Vec4V a, const Vec4V b) +{ + return internalUnitNeonSimd::BAllTrue4_R(V4IsEq(a, b)); +} + +PX_FORCE_INLINE PxU32 V4AnyGrtr3(const Vec4V a, const Vec4V b) +{ + return internalUnitNeonSimd::BAnyTrue3_R(V4IsGrtr(a, b)); +} + +PX_FORCE_INLINE Vec4V V4Round(const Vec4V a) +{ + // truncate(a + (0.5f - sign(a))) + const Vec4V half = V4Load(0.5f); + const float32x4_t sign = vcvtq_f32_u32((vshrq_n_u32(vreinterpretq_u32_f32(a), 31))); + const Vec4V aPlusHalf = V4Add(a, half); + const Vec4V aRound = V4Sub(aPlusHalf, sign); + return vcvtq_f32_s32(vcvtq_s32_f32(aRound)); +} + +PX_FORCE_INLINE Vec4V V4Sin(const Vec4V a) +{ + const Vec4V recipTwoPi = V4LoadA(g_PXReciprocalTwoPi.f); + const Vec4V twoPi = V4LoadA(g_PXTwoPi.f); + const Vec4V tmp = V4Mul(a, recipTwoPi); + const Vec4V b = V4Round(tmp); + const Vec4V V1 = V4NegMulSub(twoPi, b, a); + + // sin(V) ~= V - V^3 / 3! + V^5 / 5! - V^7 / 7! + V^9 / 9! - V^11 / 11! + V^13 / 13! - + // V^15 / 15! + V^17 / 17! - V^19 / 19! + V^21 / 21! - V^23 / 23! (for -PI <= V < PI) + const Vec4V V2 = V4Mul(V1, V1); + const Vec4V V3 = V4Mul(V2, V1); + const Vec4V V5 = V4Mul(V3, V2); + const Vec4V V7 = V4Mul(V5, V2); + const Vec4V V9 = V4Mul(V7, V2); + const Vec4V V11 = V4Mul(V9, V2); + const Vec4V V13 = V4Mul(V11, V2); + const Vec4V V15 = V4Mul(V13, V2); + const Vec4V V17 = V4Mul(V15, V2); + const Vec4V V19 = V4Mul(V17, V2); + const Vec4V V21 = V4Mul(V19, V2); + const Vec4V V23 = V4Mul(V21, V2); + + const Vec4V sinCoefficients0 = V4LoadA(g_PXSinCoefficients0.f); + const Vec4V sinCoefficients1 = V4LoadA(g_PXSinCoefficients1.f); + const Vec4V sinCoefficients2 = V4LoadA(g_PXSinCoefficients2.f); + + const FloatV S1 = V4GetY(sinCoefficients0); + const FloatV S2 = V4GetZ(sinCoefficients0); + const FloatV S3 = V4GetW(sinCoefficients0); + const FloatV S4 = V4GetX(sinCoefficients1); + const FloatV S5 = V4GetY(sinCoefficients1); + const FloatV S6 = V4GetZ(sinCoefficients1); + const FloatV S7 = V4GetW(sinCoefficients1); + const FloatV S8 = V4GetX(sinCoefficients2); + const FloatV S9 = V4GetY(sinCoefficients2); + const FloatV S10 = V4GetZ(sinCoefficients2); + const FloatV S11 = V4GetW(sinCoefficients2); + + Vec4V Result; + Result = V4ScaleAdd(V3, S1, V1); + Result = V4ScaleAdd(V5, S2, Result); + Result = V4ScaleAdd(V7, S3, Result); + Result = V4ScaleAdd(V9, S4, Result); + Result = V4ScaleAdd(V11, S5, Result); + Result = V4ScaleAdd(V13, S6, Result); + Result = V4ScaleAdd(V15, S7, Result); + Result = V4ScaleAdd(V17, S8, Result); + Result = V4ScaleAdd(V19, S9, Result); + Result = V4ScaleAdd(V21, S10, Result); + Result = V4ScaleAdd(V23, S11, Result); + + return Result; +} + +PX_FORCE_INLINE Vec4V V4Cos(const Vec4V a) +{ + const Vec4V recipTwoPi = V4LoadA(g_PXReciprocalTwoPi.f); + const Vec4V twoPi = V4LoadA(g_PXTwoPi.f); + const Vec4V tmp = V4Mul(a, recipTwoPi); + const Vec4V b = V4Round(tmp); + const Vec4V V1 = V4NegMulSub(twoPi, b, a); + + // cos(V) ~= 1 - V^2 / 2! + V^4 / 4! - V^6 / 6! + V^8 / 8! - V^10 / 10! + V^12 / 12! - + // V^14 / 14! + V^16 / 16! - V^18 / 18! + V^20 / 20! - V^22 / 22! (for -PI <= V < PI) + const Vec4V V2 = V4Mul(V1, V1); + const Vec4V V4 = V4Mul(V2, V2); + const Vec4V V6 = V4Mul(V4, V2); + const Vec4V V8 = V4Mul(V4, V4); + const Vec4V V10 = V4Mul(V6, V4); + const Vec4V V12 = V4Mul(V6, V6); + const Vec4V V14 = V4Mul(V8, V6); + const Vec4V V16 = V4Mul(V8, V8); + const Vec4V V18 = V4Mul(V10, V8); + const Vec4V V20 = V4Mul(V10, V10); + const Vec4V V22 = V4Mul(V12, V10); + + const Vec4V cosCoefficients0 = V4LoadA(g_PXCosCoefficients0.f); + const Vec4V cosCoefficients1 = V4LoadA(g_PXCosCoefficients1.f); + const Vec4V cosCoefficients2 = V4LoadA(g_PXCosCoefficients2.f); + + const FloatV C1 = V4GetY(cosCoefficients0); + const FloatV C2 = V4GetZ(cosCoefficients0); + const FloatV C3 = V4GetW(cosCoefficients0); + const FloatV C4 = V4GetX(cosCoefficients1); + const FloatV C5 = V4GetY(cosCoefficients1); + const FloatV C6 = V4GetZ(cosCoefficients1); + const FloatV C7 = V4GetW(cosCoefficients1); + const FloatV C8 = V4GetX(cosCoefficients2); + const FloatV C9 = V4GetY(cosCoefficients2); + const FloatV C10 = V4GetZ(cosCoefficients2); + const FloatV C11 = V4GetW(cosCoefficients2); + + Vec4V Result; + Result = V4ScaleAdd(V2, C1, V4One()); + Result = V4ScaleAdd(V4, C2, Result); + Result = V4ScaleAdd(V6, C3, Result); + Result = V4ScaleAdd(V8, C4, Result); + Result = V4ScaleAdd(V10, C5, Result); + Result = V4ScaleAdd(V12, C6, Result); + Result = V4ScaleAdd(V14, C7, Result); + Result = V4ScaleAdd(V16, C8, Result); + Result = V4ScaleAdd(V18, C9, Result); + Result = V4ScaleAdd(V20, C10, Result); + Result = V4ScaleAdd(V22, C11, Result); + + return Result; +} + +PX_FORCE_INLINE void V4Transpose(Vec4V& col0, Vec4V& col1, Vec4V& col2, Vec4V& col3) +{ + const float32x4x2_t v0v1 = vzipq_f32(col0, col2); + const float32x4x2_t v2v3 = vzipq_f32(col1, col3); + const float32x4x2_t zip0 = vzipq_f32(v0v1.val[0], v2v3.val[0]); + const float32x4x2_t zip1 = vzipq_f32(v0v1.val[1], v2v3.val[1]); + col0 = zip0.val[0]; + col1 = zip0.val[1]; + col2 = zip1.val[0]; + col3 = zip1.val[1]; +} + +////////////////////////////////// +// VEC4V +////////////////////////////////// + +PX_FORCE_INLINE BoolV BFFFF() +{ + return vmovq_n_u32(0); +} + +PX_FORCE_INLINE BoolV BFFFT() +{ + const uint32x2_t zeros = vmov_n_u32(0); + const uint32x2_t ones = vmov_n_u32(0xffffFFFF); + const uint32x2_t zo = vext_u32(zeros, ones, 1); + return vcombine_u32(zeros, zo); +} + +PX_FORCE_INLINE BoolV BFFTF() +{ + const uint32x2_t zeros = vmov_n_u32(0); + const uint32x2_t ones = vmov_n_u32(0xffffFFFF); + const uint32x2_t oz = vext_u32(ones, zeros, 1); + return vcombine_u32(zeros, oz); +} + +PX_FORCE_INLINE BoolV BFFTT() +{ + const uint32x2_t zeros = vmov_n_u32(0); + const uint32x2_t ones = vmov_n_u32(0xffffFFFF); + return vcombine_u32(zeros, ones); +} + +PX_FORCE_INLINE BoolV BFTFF() +{ + const uint32x2_t zeros = vmov_n_u32(0); + const uint32x2_t ones = vmov_n_u32(0xffffFFFF); + const uint32x2_t zo = vext_u32(zeros, ones, 1); + return vcombine_u32(zo, zeros); +} + +PX_FORCE_INLINE BoolV BFTFT() +{ + const uint32x2_t zeros = vmov_n_u32(0); + const uint32x2_t ones = vmov_n_u32(0xffffFFFF); + const uint32x2_t zo = vext_u32(zeros, ones, 1); + return vcombine_u32(zo, zo); +} + +PX_FORCE_INLINE BoolV BFTTF() +{ + const uint32x2_t zeros = vmov_n_u32(0); + const uint32x2_t ones = vmov_n_u32(0xffffFFFF); + const uint32x2_t zo = vext_u32(zeros, ones, 1); + const uint32x2_t oz = vext_u32(ones, zeros, 1); + return vcombine_u32(zo, oz); +} + +PX_FORCE_INLINE BoolV BFTTT() +{ + const uint32x2_t zeros = vmov_n_u32(0); + const uint32x2_t ones = vmov_n_u32(0xffffFFFF); + const uint32x2_t zo = vext_u32(zeros, ones, 1); + return vcombine_u32(zo, ones); +} + +PX_FORCE_INLINE BoolV BTFFF() +{ + const uint32x2_t zeros = vmov_n_u32(0); + const uint32x2_t ones = vmov_n_u32(0xffffFFFF); + // const uint32x2_t zo = vext_u32(zeros, ones, 1); + const uint32x2_t oz = vext_u32(ones, zeros, 1); + return vcombine_u32(oz, zeros); +} + +PX_FORCE_INLINE BoolV BTFFT() +{ + const uint32x2_t zeros = vmov_n_u32(0); + const uint32x2_t ones = vmov_n_u32(0xffffFFFF); + const uint32x2_t zo = vext_u32(zeros, ones, 1); + const uint32x2_t oz = vext_u32(ones, zeros, 1); + return vcombine_u32(oz, zo); +} + +PX_FORCE_INLINE BoolV BTFTF() +{ + const uint32x2_t zeros = vmov_n_u32(0); + const uint32x2_t ones = vmov_n_u32(0xffffFFFF); + const uint32x2_t oz = vext_u32(ones, zeros, 1); + return vcombine_u32(oz, oz); +} + +PX_FORCE_INLINE BoolV BTFTT() +{ + const uint32x2_t zeros = vmov_n_u32(0); + const uint32x2_t ones = vmov_n_u32(0xffffFFFF); + const uint32x2_t oz = vext_u32(ones, zeros, 1); + return vcombine_u32(oz, ones); +} + +PX_FORCE_INLINE BoolV BTTFF() +{ + const uint32x2_t zeros = vmov_n_u32(0); + const uint32x2_t ones = vmov_n_u32(0xffffFFFF); + return vcombine_u32(ones, zeros); +} + +PX_FORCE_INLINE BoolV BTTFT() +{ + const uint32x2_t zeros = vmov_n_u32(0); + const uint32x2_t ones = vmov_n_u32(0xffffFFFF); + const uint32x2_t zo = vext_u32(zeros, ones, 1); + return vcombine_u32(ones, zo); +} + +PX_FORCE_INLINE BoolV BTTTF() +{ + const uint32x2_t zeros = vmov_n_u32(0); + const uint32x2_t ones = vmov_n_u32(0xffffFFFF); + const uint32x2_t oz = vext_u32(ones, zeros, 1); + return vcombine_u32(ones, oz); +} + +PX_FORCE_INLINE BoolV BTTTT() +{ + return vmovq_n_u32(0xffffFFFF); +} + +PX_FORCE_INLINE BoolV BXMask() +{ + return BTFFF(); +} + +PX_FORCE_INLINE BoolV BYMask() +{ + return BFTFF(); +} + +PX_FORCE_INLINE BoolV BZMask() +{ + return BFFTF(); +} + +PX_FORCE_INLINE BoolV BWMask() +{ + return BFFFT(); +} + +PX_FORCE_INLINE BoolV BGetX(const BoolV f) +{ + const uint32x2_t fLow = vget_low_u32(f); + return vdupq_lane_u32(fLow, 0); +} + +PX_FORCE_INLINE BoolV BGetY(const BoolV f) +{ + const uint32x2_t fLow = vget_low_u32(f); + return vdupq_lane_u32(fLow, 1); +} + +PX_FORCE_INLINE BoolV BGetZ(const BoolV f) +{ + const uint32x2_t fHigh = vget_high_u32(f); + return vdupq_lane_u32(fHigh, 0); +} + +PX_FORCE_INLINE BoolV BGetW(const BoolV f) +{ + const uint32x2_t fHigh = vget_high_u32(f); + return vdupq_lane_u32(fHigh, 1); +} + +PX_FORCE_INLINE BoolV BSetX(const BoolV v, const BoolV f) +{ + return vbslq_u32(BFTTT(), v, f); +} + +PX_FORCE_INLINE BoolV BSetY(const BoolV v, const BoolV f) +{ + return vbslq_u32(BTFTT(), v, f); +} + +PX_FORCE_INLINE BoolV BSetZ(const BoolV v, const BoolV f) +{ + return vbslq_u32(BTTFT(), v, f); +} + +PX_FORCE_INLINE BoolV BSetW(const BoolV v, const BoolV f) +{ + return vbslq_u32(BTTTF(), v, f); +} + +PX_FORCE_INLINE BoolV BAnd(const BoolV a, const BoolV b) +{ + return vandq_u32(a, b); +} + +PX_FORCE_INLINE BoolV BNot(const BoolV a) +{ + return vmvnq_u32(a); +} + +PX_FORCE_INLINE BoolV BAndNot(const BoolV a, const BoolV b) +{ + // return vbicq_u32(a, b); + return vandq_u32(a, vmvnq_u32(b)); +} + +PX_FORCE_INLINE BoolV BOr(const BoolV a, const BoolV b) +{ + return vorrq_u32(a, b); +} + +PX_FORCE_INLINE BoolV BAllTrue4(const BoolV a) +{ + const uint32x2_t allTrue = vmov_n_u32(0xffffFFFF); + const uint16x4_t dHigh = vget_high_u16(vreinterpretq_u16_u32(a)); + const uint16x4_t dLow = vmovn_u32(a); + uint16x8_t combined = vcombine_u16(dLow, dHigh); + const uint32x2_t finalReduce = vreinterpret_u32_u8(vmovn_u16(combined)); + const uint32x2_t result = vceq_u32(finalReduce, allTrue); + return vdupq_lane_u32(result, 0); +} + +PX_FORCE_INLINE BoolV BAnyTrue4(const BoolV a) +{ + const uint32x2_t allTrue = vmov_n_u32(0xffffFFFF); + const uint16x4_t dHigh = vget_high_u16(vreinterpretq_u16_u32(a)); + const uint16x4_t dLow = vmovn_u32(a); + uint16x8_t combined = vcombine_u16(dLow, dHigh); + const uint32x2_t finalReduce = vreinterpret_u32_u8(vmovn_u16(combined)); + const uint32x2_t result = vtst_u32(finalReduce, allTrue); + return vdupq_lane_u32(result, 0); +} + +PX_FORCE_INLINE BoolV BAllTrue3(const BoolV a) +{ + const uint32x2_t allTrue3 = vmov_n_u32(0x00ffFFFF); + const uint16x4_t dHigh = vget_high_u16(vreinterpretq_u16_u32(a)); + const uint16x4_t dLow = vmovn_u32(a); + uint16x8_t combined = vcombine_u16(dLow, dHigh); + const uint32x2_t finalReduce = vreinterpret_u32_u8(vmovn_u16(combined)); + const uint32x2_t result = vceq_u32(vand_u32(finalReduce, allTrue3), allTrue3); + return vdupq_lane_u32(result, 0); +} + +PX_FORCE_INLINE BoolV BAnyTrue3(const BoolV a) +{ + const uint32x2_t allTrue3 = vmov_n_u32(0x00ffFFFF); + const uint16x4_t dHigh = vget_high_u16(vreinterpretq_u16_u32(a)); + const uint16x4_t dLow = vmovn_u32(a); + uint16x8_t combined = vcombine_u16(dLow, dHigh); + const uint32x2_t finalReduce = vreinterpret_u32_u8(vmovn_u16(combined)); + const uint32x2_t result = vtst_u32(vand_u32(finalReduce, allTrue3), allTrue3); + return vdupq_lane_u32(result, 0); +} + +PX_FORCE_INLINE PxU32 BAllEq(const BoolV a, const BoolV b) +{ + const BoolV bTest = vceqq_u32(a, b); + return internalUnitNeonSimd::BAllTrue4_R(bTest); +} + +PX_FORCE_INLINE PxU32 BAllEqTTTT(const BoolV a) +{ + return BAllEq(a, BTTTT()); +} + +PX_FORCE_INLINE PxU32 BAllEqFFFF(const BoolV a) +{ + return BAllEq(a, BFFFF()); +} + +PX_FORCE_INLINE PxU32 BGetBitMask(const BoolV a) +{ + static PX_ALIGN(16, const PxU32) bitMaskData[4] = { 1, 2, 4, 8 }; + const uint32x4_t bitMask = *(reinterpret_cast(bitMaskData)); + const uint32x4_t t0 = vandq_u32(a, bitMask); + const uint32x2_t t1 = vpadd_u32(vget_low_u32(t0), vget_high_u32(t0)); // Pairwise add (0 + 1), (2 + 3) + return PxU32(vget_lane_u32(vpadd_u32(t1, t1), 0)); +} + +////////////////////////////////// +// MAT33V +////////////////////////////////// + +PX_FORCE_INLINE Vec3V M33MulV3(const Mat33V& a, const Vec3V b) +{ + const FloatV x = V3GetX(b); + const FloatV y = V3GetY(b); + const FloatV z = V3GetZ(b); + const Vec3V v0 = V3Scale(a.col0, x); + const Vec3V v1 = V3Scale(a.col1, y); + const Vec3V v2 = V3Scale(a.col2, z); + const Vec3V v0PlusV1 = V3Add(v0, v1); + return V3Add(v0PlusV1, v2); +} + +PX_FORCE_INLINE Vec3V M33TrnspsMulV3(const Mat33V& a, const Vec3V b) +{ + const FloatV x = V3Dot(a.col0, b); + const FloatV y = V3Dot(a.col1, b); + const FloatV z = V3Dot(a.col2, b); + return V3Merge(x, y, z); +} + +PX_FORCE_INLINE Vec3V M33MulV3AddV3(const Mat33V& A, const Vec3V b, const Vec3V c) +{ + const FloatV x = V3GetX(b); + const FloatV y = V3GetY(b); + const FloatV z = V3GetZ(b); + Vec3V result = V3ScaleAdd(A.col0, x, c); + result = V3ScaleAdd(A.col1, y, result); + return V3ScaleAdd(A.col2, z, result); +} + +PX_FORCE_INLINE Mat33V M33MulM33(const Mat33V& a, const Mat33V& b) +{ + return Mat33V(M33MulV3(a, b.col0), M33MulV3(a, b.col1), M33MulV3(a, b.col2)); +} + +PX_FORCE_INLINE Mat33V M33Add(const Mat33V& a, const Mat33V& b) +{ + return Mat33V(V3Add(a.col0, b.col0), V3Add(a.col1, b.col1), V3Add(a.col2, b.col2)); +} + +PX_FORCE_INLINE Mat33V M33Scale(const Mat33V& a, const FloatV& b) +{ + return Mat33V(V3Scale(a.col0, b), V3Scale(a.col1, b), V3Scale(a.col2, b)); +} + +PX_FORCE_INLINE Mat33V M33Inverse(const Mat33V& a) +{ + const float32x2_t zeros = vreinterpret_f32_u32(vmov_n_u32(0)); + const BoolV btttf = BTTTF(); + + const Vec3V cross01 = V3Cross(a.col0, a.col1); + const Vec3V cross12 = V3Cross(a.col1, a.col2); + const Vec3V cross20 = V3Cross(a.col2, a.col0); + const FloatV dot = V3Dot(cross01, a.col2); + const FloatV invDet = FRecipFast(dot); + + const float32x4x2_t merge = vzipq_f32(cross12, cross01); + const float32x4_t mergeh = merge.val[0]; + const float32x4_t mergel = merge.val[1]; + + // const Vec3V colInv0 = XMVectorPermute(mergeh,cross20,PxPermuteControl(0,4,1,7)); + const float32x4_t colInv0_xxyy = vzipq_f32(mergeh, cross20).val[0]; + const float32x4_t colInv0 = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(colInv0_xxyy), btttf)); + + // const Vec3V colInv1 = XMVectorPermute(mergeh,cross20,PxPermuteControl(2,5,3,7)); + const float32x2_t zw0 = vget_high_f32(mergeh); + const float32x2_t xy1 = vget_low_f32(cross20); + const float32x2_t yzero1 = vext_f32(xy1, zeros, 1); + const float32x2x2_t merge1 = vzip_f32(zw0, yzero1); + const float32x4_t colInv1 = vcombine_f32(merge1.val[0], merge1.val[1]); + + // const Vec3V colInv2 = XMVectorPermute(mergel,cross20,PxPermuteControl(0,6,1,7)); + const float32x2_t x0y0 = vget_low_f32(mergel); + const float32x2_t z1w1 = vget_high_f32(cross20); + const float32x2x2_t merge2 = vzip_f32(x0y0, z1w1); + const float32x4_t colInv2 = vcombine_f32(merge2.val[0], merge2.val[1]); + + return Mat33V(vmulq_lane_f32(colInv0, invDet, 0), vmulq_lane_f32(colInv1, invDet, 0), + vmulq_lane_f32(colInv2, invDet, 0)); +} + +PX_FORCE_INLINE Mat33V M33Trnsps(const Mat33V& a) +{ + return Mat33V(V3Merge(V3GetX(a.col0), V3GetX(a.col1), V3GetX(a.col2)), + V3Merge(V3GetY(a.col0), V3GetY(a.col1), V3GetY(a.col2)), + V3Merge(V3GetZ(a.col0), V3GetZ(a.col1), V3GetZ(a.col2))); +} + +PX_FORCE_INLINE Mat33V M33Identity() +{ + return Mat33V(V3UnitX(), V3UnitY(), V3UnitZ()); +} + +PX_FORCE_INLINE Mat33V M33Sub(const Mat33V& a, const Mat33V& b) +{ + return Mat33V(V3Sub(a.col0, b.col0), V3Sub(a.col1, b.col1), V3Sub(a.col2, b.col2)); +} + +PX_FORCE_INLINE Mat33V M33Neg(const Mat33V& a) +{ + return Mat33V(V3Neg(a.col0), V3Neg(a.col1), V3Neg(a.col2)); +} + +PX_FORCE_INLINE Mat33V M33Abs(const Mat33V& a) +{ + return Mat33V(V3Abs(a.col0), V3Abs(a.col1), V3Abs(a.col2)); +} + +PX_FORCE_INLINE Mat33V PromoteVec3V(const Vec3V v) +{ + const BoolV bTFFF = BTFFF(); + const BoolV bFTFF = BFTFF(); + const BoolV bFFTF = BTFTF(); + + const Vec3V zero = V3Zero(); + + return Mat33V(V3Sel(bTFFF, v, zero), V3Sel(bFTFF, v, zero), V3Sel(bFFTF, v, zero)); +} + +PX_FORCE_INLINE Mat33V M33Diagonal(const Vec3VArg d) +{ + const Vec3V x = V3Mul(V3UnitX(), d); + const Vec3V y = V3Mul(V3UnitY(), d); + const Vec3V z = V3Mul(V3UnitZ(), d); + return Mat33V(x, y, z); +} + +////////////////////////////////// +// MAT34V +////////////////////////////////// + +PX_FORCE_INLINE Vec3V M34MulV3(const Mat34V& a, const Vec3V b) +{ + const FloatV x = V3GetX(b); + const FloatV y = V3GetY(b); + const FloatV z = V3GetZ(b); + const Vec3V v0 = V3Scale(a.col0, x); + const Vec3V v1 = V3Scale(a.col1, y); + const Vec3V v2 = V3Scale(a.col2, z); + const Vec3V v0PlusV1 = V3Add(v0, v1); + const Vec3V v0PlusV1Plusv2 = V3Add(v0PlusV1, v2); + return V3Add(v0PlusV1Plusv2, a.col3); +} + +PX_FORCE_INLINE Vec3V M34Mul33V3(const Mat34V& a, const Vec3V b) +{ + const FloatV x = V3GetX(b); + const FloatV y = V3GetY(b); + const FloatV z = V3GetZ(b); + const Vec3V v0 = V3Scale(a.col0, x); + const Vec3V v1 = V3Scale(a.col1, y); + const Vec3V v2 = V3Scale(a.col2, z); + const Vec3V v0PlusV1 = V3Add(v0, v1); + return V3Add(v0PlusV1, v2); +} + +PX_FORCE_INLINE Vec3V M34TrnspsMul33V3(const Mat34V& a, const Vec3V b) +{ + const FloatV x = V3Dot(a.col0, b); + const FloatV y = V3Dot(a.col1, b); + const FloatV z = V3Dot(a.col2, b); + return V3Merge(x, y, z); +} + +PX_FORCE_INLINE Mat34V M34MulM34(const Mat34V& a, const Mat34V& b) +{ + return Mat34V(M34Mul33V3(a, b.col0), M34Mul33V3(a, b.col1), M34Mul33V3(a, b.col2), M34MulV3(a, b.col3)); +} + +PX_FORCE_INLINE Mat33V M34MulM33(const Mat34V& a, const Mat33V& b) +{ + return Mat33V(M34Mul33V3(a, b.col0), M34Mul33V3(a, b.col1), M34Mul33V3(a, b.col2)); +} + +PX_FORCE_INLINE Mat33V M34Mul33MM34(const Mat34V& a, const Mat34V& b) +{ + return Mat33V(M34Mul33V3(a, b.col0), M34Mul33V3(a, b.col1), M34Mul33V3(a, b.col2)); +} + +PX_FORCE_INLINE Mat34V M34Add(const Mat34V& a, const Mat34V& b) +{ + return Mat34V(V3Add(a.col0, b.col0), V3Add(a.col1, b.col1), V3Add(a.col2, b.col2), V3Add(a.col3, b.col3)); +} + +PX_FORCE_INLINE Mat33V M34Trnsps33(const Mat34V& a) +{ + return Mat33V(V3Merge(V3GetX(a.col0), V3GetX(a.col1), V3GetX(a.col2)), + V3Merge(V3GetY(a.col0), V3GetY(a.col1), V3GetY(a.col2)), + V3Merge(V3GetZ(a.col0), V3GetZ(a.col1), V3GetZ(a.col2))); +} + +////////////////////////////////// +// MAT44V +////////////////////////////////// + +PX_FORCE_INLINE Vec4V M44MulV4(const Mat44V& a, const Vec4V b) +{ + const FloatV x = V4GetX(b); + const FloatV y = V4GetY(b); + const FloatV z = V4GetZ(b); + const FloatV w = V4GetW(b); + + const Vec4V v0 = V4Scale(a.col0, x); + const Vec4V v1 = V4Scale(a.col1, y); + const Vec4V v2 = V4Scale(a.col2, z); + const Vec4V v3 = V4Scale(a.col3, w); + const Vec4V v0PlusV1 = V4Add(v0, v1); + const Vec4V v0PlusV1Plusv2 = V4Add(v0PlusV1, v2); + return V4Add(v0PlusV1Plusv2, v3); +} + +PX_FORCE_INLINE Vec4V M44TrnspsMulV4(const Mat44V& a, const Vec4V b) +{ + return V4Merge(V4Dot(a.col0, b), V4Dot(a.col1, b), V4Dot(a.col2, b), V4Dot(a.col3, b)); +} + +PX_FORCE_INLINE Mat44V M44MulM44(const Mat44V& a, const Mat44V& b) +{ + return Mat44V(M44MulV4(a, b.col0), M44MulV4(a, b.col1), M44MulV4(a, b.col2), M44MulV4(a, b.col3)); +} + +PX_FORCE_INLINE Mat44V M44Add(const Mat44V& a, const Mat44V& b) +{ + return Mat44V(V4Add(a.col0, b.col0), V4Add(a.col1, b.col1), V4Add(a.col2, b.col2), V4Add(a.col3, b.col3)); +} + +PX_FORCE_INLINE Mat44V M44Trnsps(const Mat44V& a) +{ + // asm volatile( + // "vzip.f32 %q0, %q2 \n\t" + // "vzip.f32 %q1, %q3 \n\t" + // "vzip.f32 %q0, %q1 \n\t" + // "vzip.f32 %q2, %q3 \n\t" + // : "+w" (a.col0), "+w" (a.col1), "+w" (a.col2), "+w" a.col3)); + + const float32x4x2_t v0v1 = vzipq_f32(a.col0, a.col2); + const float32x4x2_t v2v3 = vzipq_f32(a.col1, a.col3); + const float32x4x2_t zip0 = vzipq_f32(v0v1.val[0], v2v3.val[0]); + const float32x4x2_t zip1 = vzipq_f32(v0v1.val[1], v2v3.val[1]); + + return Mat44V(zip0.val[0], zip0.val[1], zip1.val[0], zip1.val[1]); +} + +PX_FORCE_INLINE Mat44V M44Inverse(const Mat44V& a) +{ + float32x4_t minor0, minor1, minor2, minor3; + float32x4_t row0, row1, row2, row3; + float32x4_t det, tmp1; + + tmp1 = vmovq_n_f32(0.0f); + row1 = vmovq_n_f32(0.0f); + row3 = vmovq_n_f32(0.0f); + + row0 = a.col0; + row1 = vextq_f32(a.col1, a.col1, 2); + row2 = a.col2; + row3 = vextq_f32(a.col3, a.col3, 2); + + tmp1 = vmulq_f32(row2, row3); + tmp1 = vrev64q_f32(tmp1); + minor0 = vmulq_f32(row1, tmp1); + minor1 = vmulq_f32(row0, tmp1); + tmp1 = vextq_f32(tmp1, tmp1, 2); + minor0 = vsubq_f32(vmulq_f32(row1, tmp1), minor0); + minor1 = vsubq_f32(vmulq_f32(row0, tmp1), minor1); + minor1 = vextq_f32(minor1, minor1, 2); + + tmp1 = vmulq_f32(row1, row2); + tmp1 = vrev64q_f32(tmp1); + minor0 = vaddq_f32(vmulq_f32(row3, tmp1), minor0); + minor3 = vmulq_f32(row0, tmp1); + tmp1 = vextq_f32(tmp1, tmp1, 2); + minor0 = vsubq_f32(minor0, vmulq_f32(row3, tmp1)); + minor3 = vsubq_f32(vmulq_f32(row0, tmp1), minor3); + minor3 = vextq_f32(minor3, minor3, 2); + + tmp1 = vmulq_f32(vextq_f32(row1, row1, 2), row3); + tmp1 = vrev64q_f32(tmp1); + row2 = vextq_f32(row2, row2, 2); + minor0 = vaddq_f32(vmulq_f32(row2, tmp1), minor0); + minor2 = vmulq_f32(row0, tmp1); + tmp1 = vextq_f32(tmp1, tmp1, 2); + minor0 = vsubq_f32(minor0, vmulq_f32(row2, tmp1)); + minor2 = vsubq_f32(vmulq_f32(row0, tmp1), minor2); + minor2 = vextq_f32(minor2, minor2, 2); + + tmp1 = vmulq_f32(row0, row1); + tmp1 = vrev64q_f32(tmp1); + minor2 = vaddq_f32(vmulq_f32(row3, tmp1), minor2); + minor3 = vsubq_f32(vmulq_f32(row2, tmp1), minor3); + tmp1 = vextq_f32(tmp1, tmp1, 2); + minor2 = vsubq_f32(vmulq_f32(row3, tmp1), minor2); + minor3 = vsubq_f32(minor3, vmulq_f32(row2, tmp1)); + + tmp1 = vmulq_f32(row0, row3); + tmp1 = vrev64q_f32(tmp1); + minor1 = vsubq_f32(minor1, vmulq_f32(row2, tmp1)); + minor2 = vaddq_f32(vmulq_f32(row1, tmp1), minor2); + tmp1 = vextq_f32(tmp1, tmp1, 2); + minor1 = vaddq_f32(vmulq_f32(row2, tmp1), minor1); + minor2 = vsubq_f32(minor2, vmulq_f32(row1, tmp1)); + + tmp1 = vmulq_f32(row0, row2); + tmp1 = vrev64q_f32(tmp1); + minor1 = vaddq_f32(vmulq_f32(row3, tmp1), minor1); + minor3 = vsubq_f32(minor3, vmulq_f32(row1, tmp1)); + tmp1 = vextq_f32(tmp1, tmp1, 2); + minor1 = vsubq_f32(minor1, vmulq_f32(row3, tmp1)); + minor3 = vaddq_f32(vmulq_f32(row1, tmp1), minor3); + + det = vmulq_f32(row0, minor0); + det = vaddq_f32(vextq_f32(det, det, 2), det); + det = vaddq_f32(vrev64q_f32(det), det); + det = vdupq_lane_f32(VRECIPE(vget_low_f32(det)), 0); + + minor0 = vmulq_f32(det, minor0); + minor1 = vmulq_f32(det, minor1); + minor2 = vmulq_f32(det, minor2); + minor3 = vmulq_f32(det, minor3); + Mat44V invTrans(minor0, minor1, minor2, minor3); + return M44Trnsps(invTrans); +} + +PX_FORCE_INLINE Vec4V V4LoadXYZW(const PxF32& x, const PxF32& y, const PxF32& z, const PxF32& w) +{ +#if PX_UWP + PX_ALIGN(16,PxF32) r[4] = {x, y, z ,w}; + return vld1q_f32((const float32_t*)r); +#else + const float32x4_t ret = { x, y, z, w }; + return ret; +#endif +} + +/* +PX_FORCE_INLINE VecU16V V4U32PK(VecU32V a, VecU32V b) +{ + return vcombine_u16(vqmovn_u32(a), vqmovn_u32(b)); +} +*/ + +PX_FORCE_INLINE VecU32V V4U32Sel(const BoolV c, const VecU32V a, const VecU32V b) +{ + return vbslq_u32(c, a, b); +} + +PX_FORCE_INLINE VecU32V V4U32or(VecU32V a, VecU32V b) +{ + return vorrq_u32(a, b); +} + +PX_FORCE_INLINE VecU32V V4U32xor(VecU32V a, VecU32V b) +{ + return veorq_u32(a, b); +} + +PX_FORCE_INLINE VecU32V V4U32and(VecU32V a, VecU32V b) +{ + return vandq_u32(a, b); +} + +PX_FORCE_INLINE VecU32V V4U32Andc(VecU32V a, VecU32V b) +{ + // return vbicq_u32(a, b); // creates gcc compiler bug in RTreeQueries.cpp + return vandq_u32(a, vmvnq_u32(b)); +} + +/* +PX_FORCE_INLINE VecU16V V4U16Or(VecU16V a, VecU16V b) +{ + return vorrq_u16(a, b); +} +*/ + +/* +PX_FORCE_INLINE VecU16V V4U16And(VecU16V a, VecU16V b) +{ + return vandq_u16(a, b); +} +*/ +/* +PX_FORCE_INLINE VecU16V V4U16Andc(VecU16V a, VecU16V b) +{ + return vbicq_u16(a, b); +} +*/ + +PX_FORCE_INLINE VecI32V I4Load(const PxI32 i) +{ + return vdupq_n_s32(i); +} + +PX_FORCE_INLINE VecI32V I4LoadU(const PxI32* i) +{ + return vld1q_s32(i); +} + +PX_FORCE_INLINE VecI32V I4LoadA(const PxI32* i) +{ + return vld1q_s32(i); +} + +PX_FORCE_INLINE VecI32V VecI32V_Add(const VecI32VArg a, const VecI32VArg b) +{ + return vaddq_s32(a, b); +} + +PX_FORCE_INLINE VecI32V VecI32V_Sub(const VecI32VArg a, const VecI32VArg b) +{ + return vsubq_s32(a, b); +} + +PX_FORCE_INLINE BoolV VecI32V_IsGrtr(const VecI32VArg a, const VecI32VArg b) +{ + return vcgtq_s32(a, b); +} + +PX_FORCE_INLINE BoolV VecI32V_IsEq(const VecI32VArg a, const VecI32VArg b) +{ + return vceqq_s32(a, b); +} + +PX_FORCE_INLINE VecI32V V4I32Sel(const BoolV c, const VecI32V a, const VecI32V b) +{ + return vbslq_s32(c, a, b); +} + +PX_FORCE_INLINE VecI32V VecI32V_Zero() +{ + return vdupq_n_s32(0); +} + +PX_FORCE_INLINE VecI32V VecI32V_One() +{ + return vdupq_n_s32(1); +} + +PX_FORCE_INLINE VecI32V VecI32V_Two() +{ + return vdupq_n_s32(2); +} + +PX_FORCE_INLINE VecI32V VecI32V_MinusOne() +{ + return vdupq_n_s32(-1); +} + +PX_FORCE_INLINE VecU32V U4Zero() +{ + return U4Load(0); +} + +PX_FORCE_INLINE VecU32V U4One() +{ + return U4Load(1); +} + +PX_FORCE_INLINE VecU32V U4Two() +{ + return U4Load(2); +} + +PX_FORCE_INLINE VecShiftV VecI32V_PrepareShift(const VecI32VArg shift) +{ + return shift; +} + +PX_FORCE_INLINE VecI32V VecI32V_LeftShift(const VecI32VArg a, const VecShiftVArg count) +{ + return vshlq_s32(a, count); +} + +PX_FORCE_INLINE VecI32V VecI32V_RightShift(const VecI32VArg a, const VecShiftVArg count) +{ + return vshlq_s32(a, VecI32V_Sub(I4Load(0), count)); +} + +PX_FORCE_INLINE VecI32V VecI32V_And(const VecI32VArg a, const VecI32VArg b) +{ + return vandq_s32(a, b); +} + +PX_FORCE_INLINE VecI32V VecI32V_Or(const VecI32VArg a, const VecI32VArg b) +{ + return vorrq_s32(a, b); +} + +PX_FORCE_INLINE VecI32V VecI32V_GetX(const VecI32VArg f) +{ + const int32x2_t fLow = vget_low_s32(f); + return vdupq_lane_s32(fLow, 0); +} + +PX_FORCE_INLINE VecI32V VecI32V_GetY(const VecI32VArg f) +{ + const int32x2_t fLow = vget_low_s32(f); + return vdupq_lane_s32(fLow, 1); +} + +PX_FORCE_INLINE VecI32V VecI32V_GetZ(const VecI32VArg f) +{ + const int32x2_t fHigh = vget_high_s32(f); + return vdupq_lane_s32(fHigh, 0); +} + +PX_FORCE_INLINE VecI32V VecI32V_GetW(const VecI32VArg f) +{ + const int32x2_t fHigh = vget_high_s32(f); + return vdupq_lane_s32(fHigh, 1); +} + +PX_FORCE_INLINE VecI32V VecI32V_Sel(const BoolV c, const VecI32VArg a, const VecI32VArg b) +{ + return vbslq_s32(c, a, b); +} + +PX_FORCE_INLINE void PxI32_From_VecI32V(const VecI32VArg a, PxI32* i) +{ + *i = vgetq_lane_s32(a, 0); +} + +PX_FORCE_INLINE VecI32V VecI32V_Merge(const VecI32VArg a, const VecI32VArg b, const VecI32VArg c, const VecI32VArg d) +{ + const int32x2_t aLow = vget_low_s32(a); + const int32x2_t bLow = vget_low_s32(b); + const int32x2_t cLow = vget_low_s32(c); + const int32x2_t dLow = vget_low_s32(d); + + const int32x2_t low = vext_s32(aLow, bLow, 1); + const int32x2_t high = vext_s32(cLow, dLow, 1); + + return vcombine_s32(low, high); +} + +PX_FORCE_INLINE VecI32V VecI32V_From_BoolV(const BoolVArg a) +{ + return vreinterpretq_s32_u32(a); +} + +PX_FORCE_INLINE VecU32V VecU32V_From_BoolV(const BoolVArg a) +{ + return a; +} + +/* +template PX_FORCE_INLINE VecI32V V4ISplat() +{ + return vdupq_n_s32(a); +} + +template PX_FORCE_INLINE VecU32V V4USplat() +{ + return vdupq_n_u32(a); +} +*/ + +/* +PX_FORCE_INLINE void V4U16StoreAligned(VecU16V val, VecU16V* address) +{ + vst1q_u16((uint16_t*)address, val); +} +*/ + +PX_FORCE_INLINE void V4U32StoreAligned(VecU32V val, VecU32V* address) +{ + vst1q_u32(reinterpret_cast(address), val); +} + +PX_FORCE_INLINE Vec4V V4LoadAligned(Vec4V* addr) +{ + return vld1q_f32(reinterpret_cast(addr)); +} + +PX_FORCE_INLINE Vec4V V4LoadUnaligned(Vec4V* addr) +{ + return vld1q_f32(reinterpret_cast(addr)); +} + +PX_FORCE_INLINE Vec4V V4Andc(const Vec4V a, const VecU32V b) +{ + return vreinterpretq_f32_u32(V4U32Andc(vreinterpretq_u32_f32(a), b)); +} + +PX_FORCE_INLINE VecU32V V4IsGrtrV32u(const Vec4V a, const Vec4V b) +{ + return V4IsGrtr(a, b); +} + +PX_FORCE_INLINE VecU16V V4U16LoadAligned(VecU16V* addr) +{ + return vld1q_u16(reinterpret_cast(addr)); +} + +PX_FORCE_INLINE VecU16V V4U16LoadUnaligned(VecU16V* addr) +{ + return vld1q_u16(reinterpret_cast(addr)); +} + +PX_FORCE_INLINE VecU16V V4U16CompareGt(VecU16V a, VecU16V b) +{ + return vcgtq_u16(a, b); +} + +PX_FORCE_INLINE VecU16V V4I16CompareGt(VecI16V a, VecI16V b) +{ + return vcgtq_s16(a, b); +} + +PX_FORCE_INLINE Vec4V Vec4V_From_VecU32V(VecU32V a) +{ + return vcvtq_f32_u32(a); +} + +PX_FORCE_INLINE Vec4V Vec4V_From_VecI32V(VecI32V a) +{ + return vcvtq_f32_s32(a); +} + +PX_FORCE_INLINE VecI32V VecI32V_From_Vec4V(Vec4V a) +{ + return vcvtq_s32_f32(a); +} + +PX_FORCE_INLINE Vec4V Vec4V_ReinterpretFrom_VecU32V(VecU32V a) +{ + return vreinterpretq_f32_u32(a); +} + +PX_FORCE_INLINE Vec4V Vec4V_ReinterpretFrom_VecI32V(VecI32V a) +{ + return vreinterpretq_f32_s32(a); +} + +PX_FORCE_INLINE VecU32V VecU32V_ReinterpretFrom_Vec4V(Vec4V a) +{ + return vreinterpretq_u32_f32(a); +} + +PX_FORCE_INLINE VecI32V VecI32V_ReinterpretFrom_Vec4V(Vec4V a) +{ + return vreinterpretq_s32_f32(a); +} + +template +PX_FORCE_INLINE BoolV BSplatElement(BoolV a) +{ + if(index < 2) + { + return vdupq_lane_u32(vget_low_u32(a), index); + } + else if(index == 2) + { + return vdupq_lane_u32(vget_high_u32(a), 0); + } + else if(index == 3) + { + return vdupq_lane_u32(vget_high_u32(a), 1); + } +} + +template +PX_FORCE_INLINE VecU32V V4U32SplatElement(VecU32V a) +{ + if(index < 2) + { + return vdupq_lane_u32(vget_low_u32(a), index); + } + else if(index == 2) + { + return vdupq_lane_u32(vget_high_u32(a), 0); + } + else if(index == 3) + { + return vdupq_lane_u32(vget_high_u32(a), 1); + } +} + +template +PX_FORCE_INLINE Vec4V V4SplatElement(Vec4V a) +{ +#if PX_UWP + if(index == 0) + { + return vdupq_lane_f32(vget_low_f32(a), 0); + } + else if (index == 1) + { + return vdupq_lane_f32(vget_low_f32(a), 1); + } +#else + if(index < 2) + { + return vdupq_lane_f32(vget_low_f32(a), index); + } +#endif + else if(index == 2) + { + return vdupq_lane_f32(vget_high_f32(a), 0); + } + else if(index == 3) + { + return vdupq_lane_f32(vget_high_f32(a), 1); + } +} + +PX_FORCE_INLINE VecU32V U4LoadXYZW(PxU32 x, PxU32 y, PxU32 z, PxU32 w) +{ +#if PX_UWP + PX_ALIGN(16,PxU32) r[4] = {x, y, z ,w}; + return vld1q_u32((const uint32_t*)r); +#else + const uint32x4_t ret = { x, y, z, w }; + return ret; +#endif +} + +PX_FORCE_INLINE VecU32V U4Load(const PxU32 i) +{ + return vdupq_n_u32(i); +} + +PX_FORCE_INLINE VecU32V U4LoadU(const PxU32* i) +{ + return vld1q_u32(i); +} + +PX_FORCE_INLINE VecU32V U4LoadA(const PxU32* i) +{ + return vld1q_u32(i); +} + +PX_FORCE_INLINE Vec4V V4Ceil(const Vec4V in) +{ + const float32x4_t ones = vdupq_n_f32(1.0f); + const float32x4_t rdToZero = vcvtq_f32_s32(vcvtq_s32_f32(in)); + const float32x4_t rdToZeroPlusOne = vaddq_f32(rdToZero, ones); + const uint32x4_t gt = vcgtq_f32(in, rdToZero); + return vbslq_f32(gt, rdToZeroPlusOne, rdToZero); +} + +PX_FORCE_INLINE Vec4V V4Floor(const Vec4V in) +{ + const float32x4_t ones = vdupq_n_f32(1.0f); + const float32x4_t rdToZero = vcvtq_f32_s32(vcvtq_s32_f32(in)); + const float32x4_t rdToZeroMinusOne = vsubq_f32(rdToZero, ones); + const uint32x4_t lt = vcltq_f32(in, rdToZero); + return vbslq_f32(lt, rdToZeroMinusOne, rdToZero); +} + +PX_FORCE_INLINE VecU32V V4ConvertToU32VSaturate(const Vec4V in, PxU32 power) +{ + PX_ASSERT(power == 0 && "Non-zero power not supported in convertToU32VSaturate"); + PX_UNUSED(power); // prevent warning in release builds + + return vcvtq_u32_f32(in); +} + +PX_FORCE_INLINE void QuatGetMat33V(const QuatVArg q, Vec3V& column0, Vec3V& column1, Vec3V& column2) +{ + const FloatV one = FOne(); + const FloatV x = V4GetX(q); + const FloatV y = V4GetY(q); + const FloatV z = V4GetZ(q); + const FloatV w = V4GetW(q); + + const FloatV x2 = FAdd(x, x); + const FloatV y2 = FAdd(y, y); + const FloatV z2 = FAdd(z, z); + + const FloatV xx = FMul(x2, x); + const FloatV yy = FMul(y2, y); + const FloatV zz = FMul(z2, z); + + const FloatV xy = FMul(x2, y); + const FloatV xz = FMul(x2, z); + const FloatV xw = FMul(x2, w); + + const FloatV yz = FMul(y2, z); + const FloatV yw = FMul(y2, w); + const FloatV zw = FMul(z2, w); + + const FloatV v = FSub(one, xx); + + column0 = V3Merge(FSub(FSub(one, yy), zz), FAdd(xy, zw), FSub(xz, yw)); + column1 = V3Merge(FSub(xy, zw), FSub(v, zz), FAdd(yz, xw)); + column2 = V3Merge(FAdd(xz, yw), FSub(yz, xw), FSub(v, yy)); +} + +} // namespace aos +} // namespace shdfnd +} // namespace physx + +#endif // PSFOUNDATION_PSUNIXNEONINLINEAOS_H diff --git a/sources/PhysX/PhysX/source/foundation/include/windows/PsWindowsAoS.h b/sources/PhysX/PhysX/source/foundation/include/windows/PsWindowsAoS.h new file mode 100644 index 00000000..7fefc348 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/windows/PsWindowsAoS.h @@ -0,0 +1,142 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSWINDOWSAOS_H +#define PSFOUNDATION_PSWINDOWSAOS_H + +// no includes here! this file should be included from PxcVecMath.h only!!! + +#if !COMPILE_VECTOR_INTRINSICS +#error Vector intrinsics should not be included when using scalar implementation. +#endif + +namespace physx +{ +namespace shdfnd +{ +namespace aos +{ + +typedef __m128 FloatV; +typedef __m128 Vec3V; +typedef __m128 Vec4V; +typedef __m128 BoolV; +typedef __m128 VecU32V; +typedef __m128 VecI32V; +typedef __m128 VecU16V; +typedef __m128 VecI16V; +typedef __m128 QuatV; + +#define FloatVArg FloatV & +#define Vec3VArg Vec3V & +#define Vec4VArg Vec4V & +#define BoolVArg BoolV & +#define VecU32VArg VecU32V & +#define VecI32VArg VecI32V & +#define VecU16VArg VecU16V & +#define VecI16VArg VecI16V & +#define QuatVArg QuatV & + +// Optimization for situations in which you cross product multiple vectors with the same vector. +// Avoids 2X shuffles per product +struct VecCrossV +{ + Vec3V mL1; + Vec3V mR1; +}; + +struct VecShiftV +{ + VecI32V shift; +}; +#define VecShiftVArg VecShiftV & + +PX_ALIGN_PREFIX(16) +struct Mat33V +{ + Mat33V() + { + } + Mat33V(const Vec3V& c0, const Vec3V& c1, const Vec3V& c2) : col0(c0), col1(c1), col2(c2) + { + } + Vec3V PX_ALIGN(16, col0); + Vec3V PX_ALIGN(16, col1); + Vec3V PX_ALIGN(16, col2); +} PX_ALIGN_SUFFIX(16); + +PX_ALIGN_PREFIX(16) +struct Mat34V +{ + Mat34V() + { + } + Mat34V(const Vec3V& c0, const Vec3V& c1, const Vec3V& c2, const Vec3V& c3) : col0(c0), col1(c1), col2(c2), col3(c3) + { + } + Vec3V PX_ALIGN(16, col0); + Vec3V PX_ALIGN(16, col1); + Vec3V PX_ALIGN(16, col2); + Vec3V PX_ALIGN(16, col3); +} PX_ALIGN_SUFFIX(16); + +PX_ALIGN_PREFIX(16) +struct Mat43V +{ + Mat43V() + { + } + Mat43V(const Vec4V& c0, const Vec4V& c1, const Vec4V& c2) : col0(c0), col1(c1), col2(c2) + { + } + Vec4V PX_ALIGN(16, col0); + Vec4V PX_ALIGN(16, col1); + Vec4V PX_ALIGN(16, col2); +} PX_ALIGN_SUFFIX(16); + +PX_ALIGN_PREFIX(16) +struct Mat44V +{ + Mat44V() + { + } + Mat44V(const Vec4V& c0, const Vec4V& c1, const Vec4V& c2, const Vec4V& c3) : col0(c0), col1(c1), col2(c2), col3(c3) + { + } + Vec4V PX_ALIGN(16, col0); + Vec4V PX_ALIGN(16, col1); + Vec4V PX_ALIGN(16, col2); + Vec4V PX_ALIGN(16, col3); +} PX_ALIGN_SUFFIX(16); + +} // namespace aos +} // namespace shdfnd +} // namespace physx + +#endif // PSFOUNDATION_PSWINDOWSAOS_H diff --git a/sources/PhysX/PhysX/source/foundation/include/windows/PsWindowsFPU.h b/sources/PhysX/PhysX/source/foundation/include/windows/PsWindowsFPU.h new file mode 100644 index 00000000..c1806799 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/windows/PsWindowsFPU.h @@ -0,0 +1,51 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSWINDOWSFPU_H +#define PSFOUNDATION_PSWINDOWSFPU_H + +PX_INLINE physx::shdfnd::SIMDGuard::SIMDGuard() +{ +#if !PX_ARM && !PX_A64 + mControlWord = _mm_getcsr(); + // set default (disable exceptions: _MM_MASK_MASK) and FTZ (_MM_FLUSH_ZERO_ON), DAZ (_MM_DENORMALS_ZERO_ON: (1<<6)) + _mm_setcsr(_MM_MASK_MASK | _MM_FLUSH_ZERO_ON | (1 << 6)); +#endif +} + +PX_INLINE physx::shdfnd::SIMDGuard::~SIMDGuard() +{ +#if !PX_ARM && !PX_A64 + // restore control word and clear any exception flags + // (setting exception state flags cause exceptions on the first following fp operation) + _mm_setcsr(mControlWord & ~_MM_EXCEPT_MASK); +#endif +} + +#endif // #ifndef PSFOUNDATION_PSWINDOWSFPU_H diff --git a/sources/PhysX/PhysX/source/foundation/include/windows/PsWindowsInclude.h b/sources/PhysX/PhysX/source/foundation/include/windows/PsWindowsInclude.h new file mode 100644 index 00000000..68caaebe --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/windows/PsWindowsInclude.h @@ -0,0 +1,104 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSWINDOWSINCLUDE_H +#define PSFOUNDATION_PSWINDOWSINCLUDE_H + +#include "Ps.h" + +#ifndef _WIN32 +#error "This file should only be included by Windows builds!!" +#endif + +#ifdef _WINDOWS_ // windows already included +#error "Only include windows.h through this file!!" +#endif + +// We only support >= Windows XP, and we need this for critical section and +// Setting this hides some important APIs (e.g. LoadPackagedLibrary), so don't do it +#if !PX_UWP +#define _WIN32_WINNT 0x0501 +#else +#define _WIN32_WINNT 0x0602 +#endif + +// turn off as much as we can for windows. All we really need is the thread functions(critical sections/Interlocked* +// etc) +#define NOGDICAPMASKS +#define NOVIRTUALKEYCODES +#define NOWINMESSAGES +#define NOWINSTYLES +#define NOSYSMETRICS +#define NOMENUS +#define NOICONS +#define NOKEYSTATES +#define NOSYSCOMMANDS +#define NORASTEROPS +#define NOSHOWWINDOW +#define NOATOM +#define NOCLIPBOARD +#define NOCOLOR +#define NOCTLMGR +#define NODRAWTEXT +#define NOGDI +#define NOMB +#define NOMEMMGR +#define NOMETAFILE +#define NOMINMAX +#define NOOPENFILE +#define NOSCROLL +#define NOSERVICE +#define NOSOUND +#define NOTEXTMETRIC +#define NOWH +#define NOWINOFFSETS +#define NOCOMM +#define NOKANJI +#define NOHELP +#define NOPROFILER +#define NODEFERWINDOWPOS +#define NOMCX +#define WIN32_LEAN_AND_MEAN +// We need a slightly wider API surface for e.g. MultiByteToWideChar +#if !PX_UWP +#define NOUSER +#define NONLS +#define NOMSG +#endif + +#pragma warning(push) +#pragma warning(disable : 4668) //'symbol' is not defined as a preprocessor macro, replacing with '0' for 'directives' +#include +#pragma warning(pop) + +#if PX_SSE2 +#include +#endif + +#endif // #ifndef PSFOUNDATION_PSWINDOWSINCLUDE_H diff --git a/sources/PhysX/PhysX/source/foundation/include/windows/PsWindowsInlineAoS.h b/sources/PhysX/PhysX/source/foundation/include/windows/PsWindowsInlineAoS.h new file mode 100644 index 00000000..881dffb7 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/windows/PsWindowsInlineAoS.h @@ -0,0 +1,3132 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSWINDOWSINLINEAOS_H +#define PSFOUNDATION_PSWINDOWSINLINEAOS_H + +#if !COMPILE_VECTOR_INTRINSICS +#error Vector intrinsics should not be included when using scalar implementation. +#endif + +#include "../PsVecMathSSE.h" + +namespace physx +{ +namespace shdfnd +{ +namespace aos +{ + +////////////////////////////////////////////////////////////////////// +//Test that Vec3V and FloatV are legal +////////////////////////////////////////////////////////////////////// + +#define FLOAT_COMPONENTS_EQUAL_THRESHOLD 0.01f +PX_FORCE_INLINE bool isValidFloatV(const FloatV a) +{ + const PxF32 x = V4ReadX(a); + const PxF32 y = V4ReadY(a); + const PxF32 z = V4ReadZ(a); + const PxF32 w = V4ReadW(a); + + if ( + (PxAbs(x - y) < FLOAT_COMPONENTS_EQUAL_THRESHOLD) && + (PxAbs(x - z) < FLOAT_COMPONENTS_EQUAL_THRESHOLD) && + (PxAbs(x - w) < FLOAT_COMPONENTS_EQUAL_THRESHOLD) + ) + { + return true; + } + + if ( + (PxAbs((x - y) / x) < FLOAT_COMPONENTS_EQUAL_THRESHOLD) && + (PxAbs((x - z) / x) < FLOAT_COMPONENTS_EQUAL_THRESHOLD) && + (PxAbs((x - w) / x) < FLOAT_COMPONENTS_EQUAL_THRESHOLD) + ) + { + return true; + } + return false; +} + +PX_FORCE_INLINE bool isValidVec3V(const Vec3V a) +{ + //using _mm_comieq_ss to do the comparison doesn't work for NaN. + PX_ALIGN(16, PxF32 f[4]); + V4StoreA((const Vec4V&)a, f); + return f[3] == 0.0f; +} + +PX_FORCE_INLINE bool isFiniteLength(const Vec3V a) +{ + return !FAllEq(V4LengthSq(a), FZero()); +} + +PX_FORCE_INLINE bool isAligned16(void* a) +{ + return(0 == ((size_t)a & 0x0f)); +} + +//ASSERT_FINITELENGTH is deactivated because there is a lot of code that calls a simd normalisation function with zero length but then ignores the result. + +#if PX_DEBUG +#define ASSERT_ISVALIDVEC3V(a) PX_ASSERT(isValidVec3V(a)) +#define ASSERT_ISVALIDFLOATV(a) PX_ASSERT(isValidFloatV(a)) +#define ASSERT_ISALIGNED16(a) PX_ASSERT(isAligned16((void*)a)) +#define ASSERT_ISFINITELENGTH(a) //PX_ASSERT(isFiniteLength(a)) +#else +#define ASSERT_ISVALIDVEC3V(a) +#define ASSERT_ISVALIDFLOATV(a) +#define ASSERT_ISALIGNED16(a) +#define ASSERT_ISFINITELENGTH(a) +#endif +///////////////////////////////////////////////////////////////////// +////FUNCTIONS USED ONLY FOR ASSERTS IN VECTORISED IMPLEMENTATIONS +///////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////// +// USED ONLY INTERNALLY +////////////////////////////////////////////////////////////////////// + +namespace internalWindowsSimd +{ +PX_FORCE_INLINE __m128 m128_I2F(__m128i n) +{ + return _mm_castsi128_ps(n); +} + +PX_FORCE_INLINE __m128i m128_F2I(__m128 n) +{ + return _mm_castps_si128(n); +} + +PX_FORCE_INLINE PxU32 BAllTrue4_R(const BoolV a) +{ + const PxI32 moveMask = _mm_movemask_ps(a); + return PxU32(moveMask == 0xf); +} + +PX_FORCE_INLINE PxU32 BAllTrue3_R(const BoolV a) +{ + const PxI32 moveMask = _mm_movemask_ps(a); + return PxU32((moveMask & 0x7) == 0x7); +} + +PX_FORCE_INLINE PxU32 BAnyTrue4_R(const BoolV a) +{ + const PxI32 moveMask = _mm_movemask_ps(a); + return PxU32(moveMask != 0x0); +} + +PX_FORCE_INLINE PxU32 BAnyTrue3_R(const BoolV a) +{ + const PxI32 moveMask = _mm_movemask_ps(a); + return PxU32(((moveMask & 0x7) != 0x0)); +} + +PX_FORCE_INLINE PxU32 FiniteTestEq(const Vec4V a, const Vec4V b) +{ + // This is a bit of a bodge. + //_mm_comieq_ss returns 1 if either value is nan so we need to re-cast a and b with true encoded as a non-nan + // number. + // There must be a better way of doing this in sse. + const BoolV one = FOne(); + const BoolV zero = FZero(); + const BoolV a1 = V4Sel(a, one, zero); + const BoolV b1 = V4Sel(b, one, zero); + return (PxU32( + _mm_comieq_ss(a1, b1) && + _mm_comieq_ss(_mm_shuffle_ps(a1, a1, _MM_SHUFFLE(1, 1, 1, 1)), _mm_shuffle_ps(b1, b1, _MM_SHUFFLE(1, 1, 1, 1))) && + _mm_comieq_ss(_mm_shuffle_ps(a1, a1, _MM_SHUFFLE(2, 2, 2, 2)), _mm_shuffle_ps(b1, b1, _MM_SHUFFLE(2, 2, 2, 2))) && + _mm_comieq_ss(_mm_shuffle_ps(a1, a1, _MM_SHUFFLE(3, 3, 3, 3)), _mm_shuffle_ps(b1, b1, _MM_SHUFFLE(3, 3, 3, 3))))); +} + +PX_FORCE_INLINE bool hasZeroElementinFloatV(const FloatV a) +{ + ASSERT_ISVALIDFLOATV(a); + return _mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0)), FZero()) ? true : false; +} + +PX_FORCE_INLINE bool hasZeroElementInVec3V(const Vec3V a) +{ + return (_mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0)), FZero()) || + _mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 1, 1, 1)), FZero()) || + _mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2)), FZero())); +} + +PX_FORCE_INLINE bool hasZeroElementInVec4V(const Vec4V a) +{ + return (_mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0)), FZero()) || + _mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 1, 1, 1)), FZero()) || + _mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2)), FZero()) || + _mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 3, 3, 3)), FZero())); +} + +const PX_ALIGN(16, PxU32 gMaskXYZ[4]) = { 0xffffffff, 0xffffffff, 0xffffffff, 0 }; +} //internalWindowsSimd + +namespace _VecMathTests +{ +// PT: this function returns an invalid Vec3V (W!=0.0f) just for unit-testing 'isValidVec3V' +PX_FORCE_INLINE Vec3V getInvalidVec3V() +{ + const float f = 1.0f; + return _mm_load1_ps(&f); +} + +PX_FORCE_INLINE bool allElementsEqualFloatV(const FloatV a, const FloatV b) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(b); + return _mm_comieq_ss(a, b) != 0; +} + +PX_FORCE_INLINE bool allElementsEqualVec3V(const Vec3V a, const Vec3V b) +{ + return V3AllEq(a, b) != 0; +} + +PX_FORCE_INLINE bool allElementsEqualVec4V(const Vec4V a, const Vec4V b) +{ + return V4AllEq(a, b) != 0; +} + +PX_FORCE_INLINE bool allElementsEqualBoolV(const BoolV a, const BoolV b) +{ + return internalWindowsSimd::BAllTrue4_R(VecI32V_IsEq(a, b)) != 0; +} + +PX_FORCE_INLINE bool allElementsEqualVecU32V(const VecU32V a, const VecU32V b) +{ + return internalWindowsSimd::BAllTrue4_R(V4IsEqU32(a, b)) != 0; +} + +PX_FORCE_INLINE bool allElementsEqualVecI32V(const VecI32V a, const VecI32V b) +{ + BoolV c = internalWindowsSimd::m128_I2F( + _mm_cmpeq_epi32(internalWindowsSimd::m128_F2I(a), internalWindowsSimd::m128_F2I(b))); + return internalWindowsSimd::BAllTrue4_R(c) != 0; +} + +#define VECMATH_AOS_EPSILON (1e-3f) +static const FloatV minFError = FLoad(-VECMATH_AOS_EPSILON); +static const FloatV maxFError = FLoad(VECMATH_AOS_EPSILON); +static const Vec3V minV3Error = V3Load(-VECMATH_AOS_EPSILON); +static const Vec3V maxV3Error = V3Load(VECMATH_AOS_EPSILON); +static const Vec4V minV4Error = V4Load(-VECMATH_AOS_EPSILON); +static const Vec4V maxV4Error = V4Load(VECMATH_AOS_EPSILON); + +PX_FORCE_INLINE bool allElementsNearEqualFloatV(const FloatV a, const FloatV b) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(b); + const FloatV c = FSub(a, b); + return _mm_comigt_ss(c, minFError) && _mm_comilt_ss(c, maxFError); +} + +PX_FORCE_INLINE bool allElementsNearEqualVec3V(const Vec3V a, const Vec3V b) +{ + const Vec3V c = V3Sub(a, b); + return (_mm_comigt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(0, 0, 0, 0)), minV3Error) && + _mm_comilt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(0, 0, 0, 0)), maxV3Error) && + _mm_comigt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(1, 1, 1, 1)), minV3Error) && + _mm_comilt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(1, 1, 1, 1)), maxV3Error) && + _mm_comigt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(2, 2, 2, 2)), minV3Error) && + _mm_comilt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(2, 2, 2, 2)), maxV3Error)); +} + +PX_FORCE_INLINE bool allElementsNearEqualVec4V(const Vec4V a, const Vec4V b) +{ + const Vec4V c = V4Sub(a, b); + return (_mm_comigt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(0, 0, 0, 0)), minV4Error) && + _mm_comilt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(0, 0, 0, 0)), maxV4Error) && + _mm_comigt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(1, 1, 1, 1)), minV4Error) && + _mm_comilt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(1, 1, 1, 1)), maxV4Error) && + _mm_comigt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(2, 2, 2, 2)), minV4Error) && + _mm_comilt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(2, 2, 2, 2)), maxV4Error) && + _mm_comigt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(3, 3, 3, 3)), minV4Error) && + _mm_comilt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(3, 3, 3, 3)), maxV4Error)); +} +} //_VecMathTests + +PX_FORCE_INLINE bool isFiniteFloatV(const FloatV a) +{ + PxF32 f; + FStore(a, &f); + return PxIsFinite(f); + /* + const PxU32 badNumber = (_FPCLASS_SNAN | _FPCLASS_QNAN | _FPCLASS_NINF | _FPCLASS_PINF); + const FloatV vBadNum = FloatV_From_F32((PxF32&)badNumber); + const BoolV vMask = BAnd(vBadNum, a); + return FiniteTestEq(vMask, BFFFF()) == 1; + */ +} + +PX_FORCE_INLINE bool isFiniteVec3V(const Vec3V a) +{ + PX_ALIGN(16, PxF32 f[4]); + V4StoreA((Vec4V&)a, f); + return PxIsFinite(f[0]) && PxIsFinite(f[1]) && PxIsFinite(f[2]); + + /* + const PxU32 badNumber = (_FPCLASS_SNAN | _FPCLASS_QNAN | _FPCLASS_NINF | _FPCLASS_PINF); + const Vec3V vBadNum = Vec3V_From_F32((PxF32&)badNumber); + const BoolV vMask = BAnd(BAnd(vBadNum, a), BTTTF()); + return FiniteTestEq(vMask, BFFFF()) == 1; + */ +} + +PX_FORCE_INLINE bool isFiniteVec4V(const Vec4V a) +{ + PX_ALIGN(16, PxF32 f[4]); + V4StoreA(a, f); + return PxIsFinite(f[0]) && PxIsFinite(f[1]) && PxIsFinite(f[2]) && PxIsFinite(f[3]); + + /* + const PxU32 badNumber = (_FPCLASS_SNAN | _FPCLASS_QNAN | _FPCLASS_NINF | _FPCLASS_PINF); + const Vec4V vBadNum = Vec4V_From_U32((PxF32&)badNumber); + const BoolV vMask = BAnd(vBadNum, a); + + return FiniteTestEq(vMask, BFFFF()) == 1; + */ +} + +///////////////////////////////////////////////////////////////////// +////VECTORISED FUNCTION IMPLEMENTATIONS +///////////////////////////////////////////////////////////////////// + +PX_FORCE_INLINE FloatV FLoad(const PxF32 f) +{ + return _mm_load1_ps(&f); +} + +PX_FORCE_INLINE Vec3V V3Load(const PxF32 f) +{ + return _mm_set_ps(0.0f, f, f, f); +} + +PX_FORCE_INLINE Vec4V V4Load(const PxF32 f) +{ + return _mm_load1_ps(&f); +} + +PX_FORCE_INLINE BoolV BLoad(const bool f) +{ + const PxU32 i = PxU32(-(PxI32)f); + return _mm_load1_ps((float*)&i); +} + +PX_FORCE_INLINE Vec3V V3LoadA(const PxVec3& f) +{ + ASSERT_ISALIGNED16(&f); + return _mm_and_ps(_mm_load_ps(&f.x), reinterpret_cast(internalWindowsSimd::gMaskXYZ)); +} + +PX_FORCE_INLINE Vec3V V3LoadU(const PxVec3& f) +{ + return _mm_set_ps(0.0f, f.z, f.y, f.x); +} + +// w component of result is undefined +PX_FORCE_INLINE Vec3V V3LoadUnsafeA(const PxVec3& f) +{ + ASSERT_ISALIGNED16(&f); + return _mm_load_ps(&f.x); +} + +PX_FORCE_INLINE Vec3V V3LoadA(const PxF32* const f) +{ + ASSERT_ISALIGNED16(f); + return V4ClearW(_mm_load_ps(f)); +} + +PX_FORCE_INLINE Vec3V V3LoadU(const PxF32* const i) +{ + return _mm_set_ps(0.0f, i[2], i[1], i[0]); +} + +PX_FORCE_INLINE Vec3V Vec3V_From_Vec4V(Vec4V v) +{ + return V4ClearW(v); +} + +PX_FORCE_INLINE Vec3V Vec3V_From_Vec4V_WUndefined(const Vec4V v) +{ + return v; +} + +PX_FORCE_INLINE Vec4V Vec4V_From_Vec3V(Vec3V f) +{ + return f; // ok if it is implemented as the same type. +} + +PX_FORCE_INLINE Vec4V Vec4V_From_FloatV(FloatV f) +{ + return f; +} + +PX_FORCE_INLINE Vec3V Vec3V_From_FloatV(FloatV f) +{ + return Vec3V_From_Vec4V(Vec4V_From_FloatV(f)); +} + +PX_FORCE_INLINE Vec3V Vec3V_From_FloatV_WUndefined(FloatV f) +{ + return Vec3V_From_Vec4V_WUndefined(Vec4V_From_FloatV(f)); +} + +PX_FORCE_INLINE Vec4V Vec4V_From_PxVec3_WUndefined(const PxVec3& f) +{ + return _mm_set_ps(0.0f, f.z, f.y, f.x); +} + +PX_FORCE_INLINE Vec4V V4LoadA(const PxF32* const f) +{ + ASSERT_ISALIGNED16(f); + return _mm_load_ps(f); +} + +PX_FORCE_INLINE void V4StoreA(const Vec4V a, PxF32* f) +{ + ASSERT_ISALIGNED16(f); + _mm_store_ps(f, a); +} + +PX_FORCE_INLINE void V4StoreU(const Vec4V a, PxF32* f) +{ + _mm_storeu_ps(f, a); +} + +PX_FORCE_INLINE void BStoreA(const BoolV a, PxU32* f) +{ + ASSERT_ISALIGNED16(f); + _mm_store_ps((PxF32*)f, a); +} + +PX_FORCE_INLINE void U4StoreA(const VecU32V uv, PxU32* u) +{ + ASSERT_ISALIGNED16(u); + _mm_store_ps((PxF32*)u, uv); +} + +PX_FORCE_INLINE void I4StoreA(const VecI32V iv, PxI32* i) +{ + ASSERT_ISALIGNED16(i); + _mm_store_ps((PxF32*)i, iv); +} + +PX_FORCE_INLINE Vec4V V4LoadU(const PxF32* const f) +{ + return _mm_loadu_ps(f); +} + +PX_FORCE_INLINE BoolV BLoad(const bool* const f) +{ + const PX_ALIGN(16, PxU32 b[4]) = { PxU32(-(PxI32)f[0]), PxU32(-(PxI32)f[1]), + PxU32(-(PxI32)f[2]), PxU32(-(PxI32)f[3]) }; + return _mm_load_ps((float*)&b); +} + +PX_FORCE_INLINE void FStore(const FloatV a, PxF32* PX_RESTRICT f) +{ + ASSERT_ISVALIDFLOATV(a); + _mm_store_ss(f, a); +} + +PX_FORCE_INLINE void V3StoreA(const Vec3V a, PxVec3& f) +{ + ASSERT_ISALIGNED16(&f); + PX_ALIGN(16, PxF32 f2[4]); + _mm_store_ps(f2, a); + f = PxVec3(f2[0], f2[1], f2[2]); +} + +PX_FORCE_INLINE void Store_From_BoolV(const BoolV b, PxU32* b2) +{ + _mm_store_ss((PxF32*)b2, b); +} + +PX_FORCE_INLINE void V3StoreU(const Vec3V a, PxVec3& f) +{ + PX_ALIGN(16, PxF32 f2[4]); + _mm_store_ps(f2, a); + f = PxVec3(f2[0], f2[1], f2[2]); +} + +PX_FORCE_INLINE Mat33V Mat33V_From_PxMat33(const PxMat33& m) +{ + return Mat33V(V3LoadU(m.column0), V3LoadU(m.column1), V3LoadU(m.column2)); +} + +PX_FORCE_INLINE void PxMat33_From_Mat33V(const Mat33V& m, PxMat33& out) +{ + ASSERT_ISALIGNED16(&out); + V3StoreU(m.col0, out.column0); + V3StoreU(m.col1, out.column1); + V3StoreU(m.col2, out.column2); +} + +////////////////////////////////// +// FLOATV +////////////////////////////////// + +PX_FORCE_INLINE FloatV FZero() +{ + return _mm_setzero_ps(); +} + +PX_FORCE_INLINE FloatV FOne() +{ + return FLoad(1.0f); +} + +PX_FORCE_INLINE FloatV FHalf() +{ + return FLoad(0.5f); +} + +PX_FORCE_INLINE FloatV FEps() +{ + return FLoad(PX_EPS_REAL); +} + +PX_FORCE_INLINE FloatV FEps6() +{ + return FLoad(1e-6f); +} + +PX_FORCE_INLINE FloatV FMax() +{ + return FLoad(PX_MAX_REAL); +} + +PX_FORCE_INLINE FloatV FNegMax() +{ + return FLoad(-PX_MAX_REAL); +} + +PX_FORCE_INLINE FloatV IZero() +{ + const PxU32 zero = 0; + return _mm_load1_ps((PxF32*)&zero); +} + +PX_FORCE_INLINE FloatV IOne() +{ + const PxU32 one = 1; + return _mm_load1_ps((PxF32*)&one); +} + +PX_FORCE_INLINE FloatV ITwo() +{ + const PxU32 two = 2; + return _mm_load1_ps((PxF32*)&two); +} + +PX_FORCE_INLINE FloatV IThree() +{ + const PxU32 three = 3; + return _mm_load1_ps((PxF32*)&three); +} + +PX_FORCE_INLINE FloatV IFour() +{ + const PxU32 four = 4; + return _mm_load1_ps((PxF32*)&four); +} + +PX_FORCE_INLINE FloatV FNeg(const FloatV f) +{ + ASSERT_ISVALIDFLOATV(f); + return _mm_sub_ps(_mm_setzero_ps(), f); +} + +PX_FORCE_INLINE FloatV FAdd(const FloatV a, const FloatV b) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(b); + return _mm_add_ps(a, b); +} + +PX_FORCE_INLINE FloatV FSub(const FloatV a, const FloatV b) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(b); + return _mm_sub_ps(a, b); +} + +PX_FORCE_INLINE FloatV FMul(const FloatV a, const FloatV b) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(b); + return _mm_mul_ps(a, b); +} + +PX_FORCE_INLINE FloatV FDiv(const FloatV a, const FloatV b) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(b); + return _mm_div_ps(a, b); +} + +PX_FORCE_INLINE FloatV FDivFast(const FloatV a, const FloatV b) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(b); + return _mm_mul_ps(a, _mm_rcp_ps(b)); +} + +PX_FORCE_INLINE FloatV FRecip(const FloatV a) +{ + ASSERT_ISVALIDFLOATV(a); + return _mm_div_ps(FOne(), a); +} + +PX_FORCE_INLINE FloatV FRecipFast(const FloatV a) +{ + return _mm_rcp_ps(a); +} + +PX_FORCE_INLINE FloatV FRsqrt(const FloatV a) +{ + ASSERT_ISVALIDFLOATV(a); + return _mm_div_ps(FOne(), _mm_sqrt_ps(a)); +} + +PX_FORCE_INLINE FloatV FSqrt(const FloatV a) +{ + ASSERT_ISVALIDFLOATV(a); + return _mm_sqrt_ps(a); +} + +PX_FORCE_INLINE FloatV FRsqrtFast(const FloatV a) +{ + ASSERT_ISVALIDFLOATV(a); + return _mm_rsqrt_ps(a); +} + +PX_FORCE_INLINE FloatV FScaleAdd(const FloatV a, const FloatV b, const FloatV c) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(b); + ASSERT_ISVALIDFLOATV(c); + return FAdd(FMul(a, b), c); +} + +PX_FORCE_INLINE FloatV FNegScaleSub(const FloatV a, const FloatV b, const FloatV c) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(b); + ASSERT_ISVALIDFLOATV(c); + return FSub(c, FMul(a, b)); +} + +PX_FORCE_INLINE FloatV FAbs(const FloatV a) +{ + ASSERT_ISVALIDFLOATV(a); + PX_ALIGN(16, const static PxU32 absMask[4]) = { 0x7fFFffFF, 0x7fFFffFF, 0x7fFFffFF, 0x7fFFffFF }; + return _mm_and_ps(a, _mm_load_ps((PxF32*)absMask)); +} + +PX_FORCE_INLINE FloatV FSel(const BoolV c, const FloatV a, const FloatV b) +{ + PX_ASSERT(_VecMathTests::allElementsEqualBoolV(c, BTTTT()) || + _VecMathTests::allElementsEqualBoolV(c, BFFFF())); + ASSERT_ISVALIDFLOATV(_mm_or_ps(_mm_andnot_ps(c, b), _mm_and_ps(c, a))); + return _mm_or_ps(_mm_andnot_ps(c, b), _mm_and_ps(c, a)); +} + +PX_FORCE_INLINE BoolV FIsGrtr(const FloatV a, const FloatV b) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(b); + return _mm_cmpgt_ps(a, b); +} + +PX_FORCE_INLINE BoolV FIsGrtrOrEq(const FloatV a, const FloatV b) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(b); + return _mm_cmpge_ps(a, b); +} + +PX_FORCE_INLINE BoolV FIsEq(const FloatV a, const FloatV b) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(b); + return _mm_cmpeq_ps(a, b); +} + +PX_FORCE_INLINE FloatV FMax(const FloatV a, const FloatV b) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(b); + return _mm_max_ps(a, b); +} + +PX_FORCE_INLINE FloatV FMin(const FloatV a, const FloatV b) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(b); + return _mm_min_ps(a, b); +} + +PX_FORCE_INLINE FloatV FClamp(const FloatV a, const FloatV minV, const FloatV maxV) +{ + ASSERT_ISVALIDFLOATV(minV); + ASSERT_ISVALIDFLOATV(maxV); + return _mm_max_ps(_mm_min_ps(a, maxV), minV); +} + +PX_FORCE_INLINE PxU32 FAllGrtr(const FloatV a, const FloatV b) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(b); + return PxU32(_mm_comigt_ss(a, b)); +} + +PX_FORCE_INLINE PxU32 FAllGrtrOrEq(const FloatV a, const FloatV b) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(b); + return PxU32(_mm_comige_ss(a, b)); +} + +PX_FORCE_INLINE PxU32 FAllEq(const FloatV a, const FloatV b) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(b); + return PxU32(_mm_comieq_ss(a, b)); +} + +PX_FORCE_INLINE FloatV FRound(const FloatV a) +{ + ASSERT_ISVALIDFLOATV(a); + // return _mm_round_ps(a, 0x0); + const FloatV half = FLoad(0.5f); + const __m128 signBit = _mm_cvtepi32_ps(_mm_srli_epi32(_mm_cvtps_epi32(a), 31)); + const FloatV aRound = FSub(FAdd(a, half), signBit); + __m128i tmp = _mm_cvttps_epi32(aRound); + return _mm_cvtepi32_ps(tmp); +} + +PX_FORCE_INLINE FloatV FSin(const FloatV a) +{ + ASSERT_ISVALIDFLOATV(a); + // Modulo the range of the given angles such that -XM_2PI <= Angles < XM_2PI + const FloatV recipTwoPi = V4LoadA(g_PXReciprocalTwoPi.f); + const FloatV twoPi = V4LoadA(g_PXTwoPi.f); + const FloatV tmp = FMul(a, recipTwoPi); + const FloatV b = FRound(tmp); + const FloatV V1 = FNegScaleSub(twoPi, b, a); + + // sin(V) ~= V - V^3 / 3! + V^5 / 5! - V^7 / 7! + V^9 / 9! - V^11 / 11! + V^13 / 13! - + // V^15 / 15! + V^17 / 17! - V^19 / 19! + V^21 / 21! - V^23 / 23! (for -PI <= V < PI) + const FloatV V2 = FMul(V1, V1); + const FloatV V3 = FMul(V2, V1); + const FloatV V5 = FMul(V3, V2); + const FloatV V7 = FMul(V5, V2); + const FloatV V9 = FMul(V7, V2); + const FloatV V11 = FMul(V9, V2); + const FloatV V13 = FMul(V11, V2); + const FloatV V15 = FMul(V13, V2); + const FloatV V17 = FMul(V15, V2); + const FloatV V19 = FMul(V17, V2); + const FloatV V21 = FMul(V19, V2); + const FloatV V23 = FMul(V21, V2); + + const Vec4V sinCoefficients0 = V4LoadA(g_PXSinCoefficients0.f); + const Vec4V sinCoefficients1 = V4LoadA(g_PXSinCoefficients1.f); + const Vec4V sinCoefficients2 = V4LoadA(g_PXSinCoefficients2.f); + + const FloatV S1 = V4GetY(sinCoefficients0); + const FloatV S2 = V4GetZ(sinCoefficients0); + const FloatV S3 = V4GetW(sinCoefficients0); + const FloatV S4 = V4GetX(sinCoefficients1); + const FloatV S5 = V4GetY(sinCoefficients1); + const FloatV S6 = V4GetZ(sinCoefficients1); + const FloatV S7 = V4GetW(sinCoefficients1); + const FloatV S8 = V4GetX(sinCoefficients2); + const FloatV S9 = V4GetY(sinCoefficients2); + const FloatV S10 = V4GetZ(sinCoefficients2); + const FloatV S11 = V4GetW(sinCoefficients2); + + FloatV Result; + Result = FScaleAdd(S1, V3, V1); + Result = FScaleAdd(S2, V5, Result); + Result = FScaleAdd(S3, V7, Result); + Result = FScaleAdd(S4, V9, Result); + Result = FScaleAdd(S5, V11, Result); + Result = FScaleAdd(S6, V13, Result); + Result = FScaleAdd(S7, V15, Result); + Result = FScaleAdd(S8, V17, Result); + Result = FScaleAdd(S9, V19, Result); + Result = FScaleAdd(S10, V21, Result); + Result = FScaleAdd(S11, V23, Result); + + return Result; +} + +PX_FORCE_INLINE FloatV FCos(const FloatV a) +{ + ASSERT_ISVALIDFLOATV(a); + + // Modulo the range of the given angles such that -XM_2PI <= Angles < XM_2PI + const FloatV recipTwoPi = V4LoadA(g_PXReciprocalTwoPi.f); + const FloatV twoPi = V4LoadA(g_PXTwoPi.f); + const FloatV tmp = FMul(a, recipTwoPi); + const FloatV b = FRound(tmp); + const FloatV V1 = FNegScaleSub(twoPi, b, a); + + // cos(V) ~= 1 - V^2 / 2! + V^4 / 4! - V^6 / 6! + V^8 / 8! - V^10 / 10! + V^12 / 12! - + // V^14 / 14! + V^16 / 16! - V^18 / 18! + V^20 / 20! - V^22 / 22! (for -PI <= V < PI) + const FloatV V2 = FMul(V1, V1); + const FloatV V4 = FMul(V2, V2); + const FloatV V6 = FMul(V4, V2); + const FloatV V8 = FMul(V4, V4); + const FloatV V10 = FMul(V6, V4); + const FloatV V12 = FMul(V6, V6); + const FloatV V14 = FMul(V8, V6); + const FloatV V16 = FMul(V8, V8); + const FloatV V18 = FMul(V10, V8); + const FloatV V20 = FMul(V10, V10); + const FloatV V22 = FMul(V12, V10); + + const Vec4V cosCoefficients0 = V4LoadA(g_PXCosCoefficients0.f); + const Vec4V cosCoefficients1 = V4LoadA(g_PXCosCoefficients1.f); + const Vec4V cosCoefficients2 = V4LoadA(g_PXCosCoefficients2.f); + + const FloatV C1 = V4GetY(cosCoefficients0); + const FloatV C2 = V4GetZ(cosCoefficients0); + const FloatV C3 = V4GetW(cosCoefficients0); + const FloatV C4 = V4GetX(cosCoefficients1); + const FloatV C5 = V4GetY(cosCoefficients1); + const FloatV C6 = V4GetZ(cosCoefficients1); + const FloatV C7 = V4GetW(cosCoefficients1); + const FloatV C8 = V4GetX(cosCoefficients2); + const FloatV C9 = V4GetY(cosCoefficients2); + const FloatV C10 = V4GetZ(cosCoefficients2); + const FloatV C11 = V4GetW(cosCoefficients2); + + FloatV Result; + Result = FScaleAdd(C1, V2, V4One()); + Result = FScaleAdd(C2, V4, Result); + Result = FScaleAdd(C3, V6, Result); + Result = FScaleAdd(C4, V8, Result); + Result = FScaleAdd(C5, V10, Result); + Result = FScaleAdd(C6, V12, Result); + Result = FScaleAdd(C7, V14, Result); + Result = FScaleAdd(C8, V16, Result); + Result = FScaleAdd(C9, V18, Result); + Result = FScaleAdd(C10, V20, Result); + Result = FScaleAdd(C11, V22, Result); + + return Result; +} + +PX_FORCE_INLINE PxU32 FOutOfBounds(const FloatV a, const FloatV min, const FloatV max) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(min); + ASSERT_ISVALIDFLOATV(max); + const BoolV c = BOr(FIsGrtr(a, max), FIsGrtr(min, a)); + return PxU32(!BAllEqFFFF(c)); +} + +PX_FORCE_INLINE PxU32 FInBounds(const FloatV a, const FloatV min, const FloatV max) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(min); + ASSERT_ISVALIDFLOATV(max); + const BoolV c = BAnd(FIsGrtrOrEq(a, min), FIsGrtrOrEq(max, a)); + return BAllEqTTTT(c); +} + +PX_FORCE_INLINE PxU32 FOutOfBounds(const FloatV a, const FloatV bounds) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(bounds); + return FOutOfBounds(a, FNeg(bounds), bounds); +} + +PX_FORCE_INLINE PxU32 FInBounds(const FloatV a, const FloatV bounds) +{ + ASSERT_ISVALIDFLOATV(a); + ASSERT_ISVALIDFLOATV(bounds); + return FInBounds(a, FNeg(bounds), bounds); +} + +////////////////////////////////// +// VEC3V +////////////////////////////////// + +PX_FORCE_INLINE Vec3V V3Splat(const FloatV f) +{ + ASSERT_ISVALIDFLOATV(f); + const __m128 zero = V3Zero(); + const __m128 fff0 = _mm_move_ss(f, zero); + return _mm_shuffle_ps(fff0, fff0, _MM_SHUFFLE(0, 1, 2, 3)); +} + +PX_FORCE_INLINE Vec3V V3Merge(const FloatVArg x, const FloatVArg y, const FloatVArg z) +{ + ASSERT_ISVALIDFLOATV(x); + ASSERT_ISVALIDFLOATV(y); + ASSERT_ISVALIDFLOATV(z); + // static on zero causes compiler crash on x64 debug_opt + const __m128 zero = V3Zero(); + const __m128 xy = _mm_move_ss(x, y); + const __m128 z0 = _mm_move_ss(zero, z); + + return _mm_shuffle_ps(xy, z0, _MM_SHUFFLE(1, 0, 0, 1)); +} + +PX_FORCE_INLINE Vec3V V3UnitX() +{ + const PX_ALIGN(16, PxF32 x[4]) = { 1.0f, 0.0f, 0.0f, 0.0f }; + const __m128 x128 = _mm_load_ps(x); + return x128; +} + +PX_FORCE_INLINE Vec3V V3UnitY() +{ + const PX_ALIGN(16, PxF32 y[4]) = { 0.0f, 1.0f, 0.0f, 0.0f }; + const __m128 y128 = _mm_load_ps(y); + return y128; +} + +PX_FORCE_INLINE Vec3V V3UnitZ() +{ + const PX_ALIGN(16, PxF32 z[4]) = { 0.0f, 0.0f, 1.0f, 0.0f }; + const __m128 z128 = _mm_load_ps(z); + return z128; +} + +PX_FORCE_INLINE FloatV V3GetX(const Vec3V f) +{ + ASSERT_ISVALIDVEC3V(f); + return _mm_shuffle_ps(f, f, _MM_SHUFFLE(0, 0, 0, 0)); +} + +PX_FORCE_INLINE FloatV V3GetY(const Vec3V f) +{ + ASSERT_ISVALIDVEC3V(f); + return _mm_shuffle_ps(f, f, _MM_SHUFFLE(1, 1, 1, 1)); +} + +PX_FORCE_INLINE FloatV V3GetZ(const Vec3V f) +{ + ASSERT_ISVALIDVEC3V(f); + return _mm_shuffle_ps(f, f, _MM_SHUFFLE(2, 2, 2, 2)); +} + +PX_FORCE_INLINE Vec3V V3SetX(const Vec3V v, const FloatV f) +{ + ASSERT_ISVALIDVEC3V(v); + ASSERT_ISVALIDFLOATV(f); + return V4Sel(BFTTT(), v, f); +} + +PX_FORCE_INLINE Vec3V V3SetY(const Vec3V v, const FloatV f) +{ + ASSERT_ISVALIDVEC3V(v); + ASSERT_ISVALIDFLOATV(f); + return V4Sel(BTFTT(), v, f); +} + +PX_FORCE_INLINE Vec3V V3SetZ(const Vec3V v, const FloatV f) +{ + ASSERT_ISVALIDVEC3V(v); + ASSERT_ISVALIDFLOATV(f); + return V4Sel(BTTFT(), v, f); +} + +PX_FORCE_INLINE Vec3V V3ColX(const Vec3V a, const Vec3V b, const Vec3V c) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + ASSERT_ISVALIDVEC3V(c); + Vec3V r = _mm_shuffle_ps(a, c, _MM_SHUFFLE(3, 0, 3, 0)); + return V3SetY(r, V3GetX(b)); +} + +PX_FORCE_INLINE Vec3V V3ColY(const Vec3V a, const Vec3V b, const Vec3V c) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + ASSERT_ISVALIDVEC3V(c); + Vec3V r = _mm_shuffle_ps(a, c, _MM_SHUFFLE(3, 1, 3, 1)); + return V3SetY(r, V3GetY(b)); +} + +PX_FORCE_INLINE Vec3V V3ColZ(const Vec3V a, const Vec3V b, const Vec3V c) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + ASSERT_ISVALIDVEC3V(c); + Vec3V r = _mm_shuffle_ps(a, c, _MM_SHUFFLE(3, 2, 3, 2)); + return V3SetY(r, V3GetZ(b)); +} + +PX_FORCE_INLINE Vec3V V3Zero() +{ + return _mm_setzero_ps(); +} + +PX_FORCE_INLINE Vec3V V3One() +{ + return V3Load(1.0f); +} + +PX_FORCE_INLINE Vec3V V3Eps() +{ + return V3Load(PX_EPS_REAL); +} + +PX_FORCE_INLINE Vec3V V3Neg(const Vec3V f) +{ + ASSERT_ISVALIDVEC3V(f); + return _mm_sub_ps(_mm_setzero_ps(), f); +} + +PX_FORCE_INLINE Vec3V V3Add(const Vec3V a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + return _mm_add_ps(a, b); +} + +PX_FORCE_INLINE Vec3V V3Sub(const Vec3V a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + return _mm_sub_ps(a, b); +} + +PX_FORCE_INLINE Vec3V V3Scale(const Vec3V a, const FloatV b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDFLOATV(b); + return _mm_mul_ps(a, b); +} + +PX_FORCE_INLINE Vec3V V3Mul(const Vec3V a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + return _mm_mul_ps(a, b); +} + +PX_FORCE_INLINE Vec3V V3ScaleInv(const Vec3V a, const FloatV b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDFLOATV(b); + return _mm_div_ps(a, b); +} + +PX_FORCE_INLINE Vec3V V3Div(const Vec3V a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + return V4ClearW(_mm_div_ps(a, b)); +} + +PX_FORCE_INLINE Vec3V V3ScaleInvFast(const Vec3V a, const FloatV b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDFLOATV(b); + return _mm_mul_ps(a, _mm_rcp_ps(b)); +} + +PX_FORCE_INLINE Vec3V V3DivFast(const Vec3V a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + return V4ClearW(_mm_mul_ps(a, _mm_rcp_ps(b))); +} + +PX_FORCE_INLINE Vec3V V3Recip(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + const __m128 zero = V3Zero(); + const __m128 tttf = BTTTF(); + const __m128 recipA = _mm_div_ps(V3One(), a); + return V4Sel(tttf, recipA, zero); +} + +PX_FORCE_INLINE Vec3V V3RecipFast(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + const __m128 zero = V3Zero(); + const __m128 tttf = BTTTF(); + const __m128 recipA = _mm_rcp_ps(a); + return V4Sel(tttf, recipA, zero); +} + +PX_FORCE_INLINE Vec3V V3Rsqrt(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + const __m128 zero = V3Zero(); + const __m128 tttf = BTTTF(); + const __m128 recipA = _mm_div_ps(V3One(), _mm_sqrt_ps(a)); + return V4Sel(tttf, recipA, zero); +} + +PX_FORCE_INLINE Vec3V V3RsqrtFast(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + const __m128 zero = V3Zero(); + const __m128 tttf = BTTTF(); + const __m128 recipA = _mm_rsqrt_ps(a); + return V4Sel(tttf, recipA, zero); +} + +PX_FORCE_INLINE Vec3V V3ScaleAdd(const Vec3V a, const FloatV b, const Vec3V c) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDFLOATV(b); + ASSERT_ISVALIDVEC3V(c); + return V3Add(V3Scale(a, b), c); +} + +PX_FORCE_INLINE Vec3V V3NegScaleSub(const Vec3V a, const FloatV b, const Vec3V c) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDFLOATV(b); + ASSERT_ISVALIDVEC3V(c); + return V3Sub(c, V3Scale(a, b)); +} + +PX_FORCE_INLINE Vec3V V3MulAdd(const Vec3V a, const Vec3V b, const Vec3V c) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + ASSERT_ISVALIDVEC3V(c); + return V3Add(V3Mul(a, b), c); +} + +PX_FORCE_INLINE Vec3V V3NegMulSub(const Vec3V a, const Vec3V b, const Vec3V c) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + ASSERT_ISVALIDVEC3V(c); + return V3Sub(c, V3Mul(a, b)); +} + +PX_FORCE_INLINE Vec3V V3Abs(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + return V3Max(a, V3Neg(a)); +} + +PX_FORCE_INLINE FloatV V3Dot(const Vec3V a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + + const __m128 t0 = _mm_mul_ps(a, b); // aw*bw | az*bz | ay*by | ax*bx + const __m128 t1 = _mm_shuffle_ps(t0, t0, _MM_SHUFFLE(1,0,3,2)); // ay*by | ax*bx | aw*bw | az*bz + const __m128 t2 = _mm_add_ps(t0, t1); // ay*by + aw*bw | ax*bx + az*bz | aw*bw + ay*by | az*bz + ax*bx + const __m128 t3 = _mm_shuffle_ps(t2, t2, _MM_SHUFFLE(2,3,0,1)); // ax*bx + az*bz | ay*by + aw*bw | az*bz + ax*bx | aw*bw + ay*by + return _mm_add_ps(t3, t2); // ax*bx + az*bz + ay*by + aw*bw + // ay*by + aw*bw + ax*bx + az*bz + // az*bz + ax*bx + aw*bw + ay*by + // aw*bw + ay*by + az*bz + ax*bx +} + +PX_FORCE_INLINE Vec3V V3Cross(const Vec3V a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + const __m128 r1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 1, 0, 2)); // z,x,y,w + const __m128 r2 = _mm_shuffle_ps(b, b, _MM_SHUFFLE(3, 0, 2, 1)); // y,z,x,w + const __m128 l1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 0, 2, 1)); // y,z,x,w + const __m128 l2 = _mm_shuffle_ps(b, b, _MM_SHUFFLE(3, 1, 0, 2)); // z,x,y,w + return _mm_sub_ps(_mm_mul_ps(l1, l2), _mm_mul_ps(r1, r2)); +} + +PX_FORCE_INLINE VecCrossV V3PrepareCross(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + VecCrossV v; + v.mR1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 1, 0, 2)); // z,x,y,w + v.mL1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 0, 2, 1)); // y,z,x,w + return v; +} + +PX_FORCE_INLINE Vec3V V3Cross(const VecCrossV& a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V(b); + const __m128 r2 = _mm_shuffle_ps(b, b, _MM_SHUFFLE(3, 0, 2, 1)); // y,z,x,w + const __m128 l2 = _mm_shuffle_ps(b, b, _MM_SHUFFLE(3, 1, 0, 2)); // z,x,y,w + return _mm_sub_ps(_mm_mul_ps(a.mL1, l2), _mm_mul_ps(a.mR1, r2)); +} + +PX_FORCE_INLINE Vec3V V3Cross(const Vec3V a, const VecCrossV& b) +{ + ASSERT_ISVALIDVEC3V(a); + const __m128 r2 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 0, 2, 1)); // y,z,x,w + const __m128 l2 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 1, 0, 2)); // z,x,y,w + return _mm_sub_ps(_mm_mul_ps(b.mR1, r2), _mm_mul_ps(b.mL1, l2)); +} + +PX_FORCE_INLINE Vec3V V3Cross(const VecCrossV& a, const VecCrossV& b) +{ + return _mm_sub_ps(_mm_mul_ps(a.mL1, b.mR1), _mm_mul_ps(a.mR1, b.mL1)); +} + +PX_FORCE_INLINE FloatV V3Length(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + return _mm_sqrt_ps(V3Dot(a, a)); +} + +PX_FORCE_INLINE FloatV V3LengthSq(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + return V3Dot(a, a); +} + +PX_FORCE_INLINE Vec3V V3Normalize(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISFINITELENGTH(a); + return V3ScaleInv(a, _mm_sqrt_ps(V3Dot(a, a))); +} + +PX_FORCE_INLINE Vec3V V3NormalizeFast(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISFINITELENGTH(a); + return V3Scale(a, _mm_rsqrt_ps(V3Dot(a, a))); +} + +PX_FORCE_INLINE Vec3V V3NormalizeSafe(const Vec3V a, const Vec3V unsafeReturnValue) +{ + ASSERT_ISVALIDVEC3V(a); + const __m128 eps = FEps(); + const __m128 length = V3Length(a); + const __m128 isGreaterThanZero = FIsGrtr(length, eps); + return V3Sel(isGreaterThanZero, V3ScaleInv(a, length), unsafeReturnValue); +} + +PX_FORCE_INLINE Vec3V V3Sel(const BoolV c, const Vec3V a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V(_mm_or_ps(_mm_andnot_ps(c, b), _mm_and_ps(c, a))); + return _mm_or_ps(_mm_andnot_ps(c, b), _mm_and_ps(c, a)); +} + +PX_FORCE_INLINE BoolV V3IsGrtr(const Vec3V a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + return _mm_cmpgt_ps(a, b); +} + +PX_FORCE_INLINE BoolV V3IsGrtrOrEq(const Vec3V a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + return _mm_cmpge_ps(a, b); +} + +PX_FORCE_INLINE BoolV V3IsEq(const Vec3V a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + return _mm_cmpeq_ps(a, b); +} + +PX_FORCE_INLINE Vec3V V3Max(const Vec3V a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + return _mm_max_ps(a, b); +} + +PX_FORCE_INLINE Vec3V V3Min(const Vec3V a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + return _mm_min_ps(a, b); +} + +PX_FORCE_INLINE FloatV V3ExtractMax(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + const __m128 shuf1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0)); + const __m128 shuf2 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 1, 1, 1)); + const __m128 shuf3 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2)); + return _mm_max_ps(_mm_max_ps(shuf1, shuf2), shuf3); +} + +PX_FORCE_INLINE FloatV V3ExtractMin(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + const __m128 shuf1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0)); + const __m128 shuf2 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 1, 1, 1)); + const __m128 shuf3 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2)); + return _mm_min_ps(_mm_min_ps(shuf1, shuf2), shuf3); +} + +//// if(a > 0.0f) return 1.0f; else if a == 0.f return 0.f, else return -1.f; +// PX_FORCE_INLINE Vec3V V3MathSign(const Vec3V a) +//{ +// VECMATHAOS_ASSERT(isValidVec3V(a)); +// +// const __m128i ai = _mm_cvtps_epi32(a); +// const __m128i bi = _mm_cvtps_epi32(V3Neg(a)); +// const __m128 aa = _mm_cvtepi32_ps(_mm_srai_epi32(ai, 31)); +// const __m128 bb = _mm_cvtepi32_ps(_mm_srai_epi32(bi, 31)); +// return _mm_or_ps(aa, bb); +//} + +// return (a >= 0.0f) ? 1.0f : -1.0f; +PX_FORCE_INLINE Vec3V V3Sign(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + const __m128 zero = V3Zero(); + const __m128 one = V3One(); + const __m128 none = V3Neg(one); + return V3Sel(V3IsGrtrOrEq(a, zero), one, none); +} + +PX_FORCE_INLINE Vec3V V3Clamp(const Vec3V a, const Vec3V minV, const Vec3V maxV) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(minV); + ASSERT_ISVALIDVEC3V(maxV); + return V3Max(V3Min(a, maxV), minV); +} + +PX_FORCE_INLINE PxU32 V3AllGrtr(const Vec3V a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + return internalWindowsSimd::BAllTrue3_R(V4IsGrtr(a, b)); +} + +PX_FORCE_INLINE PxU32 V3AllGrtrOrEq(const Vec3V a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + return internalWindowsSimd::BAllTrue3_R(V4IsGrtrOrEq(a, b)); +} + +PX_FORCE_INLINE PxU32 V3AllEq(const Vec3V a, const Vec3V b) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(b); + return internalWindowsSimd::BAllTrue3_R(V4IsEq(a, b)); +} + +PX_FORCE_INLINE Vec3V V3Round(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + + // return _mm_round_ps(a, 0x0); + const Vec3V half = V3Load(0.5f); + const __m128 signBit = _mm_cvtepi32_ps(_mm_srli_epi32(_mm_cvtps_epi32(a), 31)); + const Vec3V aRound = V3Sub(V3Add(a, half), signBit); + __m128i tmp = _mm_cvttps_epi32(aRound); + return _mm_cvtepi32_ps(tmp); +} + +PX_FORCE_INLINE Vec3V V3Sin(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + + // Modulo the range of the given angles such that -XM_2PI <= Angles < XM_2PI + const Vec4V recipTwoPi = V4LoadA(g_PXReciprocalTwoPi.f); + const Vec4V twoPi = V4LoadA(g_PXTwoPi.f); + const Vec3V tmp = V3Scale(a, recipTwoPi); + const Vec3V b = V3Round(tmp); + const Vec3V V1 = V3NegScaleSub(b, twoPi, a); + + // sin(V) ~= V - V^3 / 3! + V^5 / 5! - V^7 / 7! + V^9 / 9! - V^11 / 11! + V^13 / 13! - + // V^15 / 15! + V^17 / 17! - V^19 / 19! + V^21 / 21! - V^23 / 23! (for -PI <= V < PI) + const Vec3V V2 = V3Mul(V1, V1); + const Vec3V V3 = V3Mul(V2, V1); + const Vec3V V5 = V3Mul(V3, V2); + const Vec3V V7 = V3Mul(V5, V2); + const Vec3V V9 = V3Mul(V7, V2); + const Vec3V V11 = V3Mul(V9, V2); + const Vec3V V13 = V3Mul(V11, V2); + const Vec3V V15 = V3Mul(V13, V2); + const Vec3V V17 = V3Mul(V15, V2); + const Vec3V V19 = V3Mul(V17, V2); + const Vec3V V21 = V3Mul(V19, V2); + const Vec3V V23 = V3Mul(V21, V2); + + const Vec4V sinCoefficients0 = V4LoadA(g_PXSinCoefficients0.f); + const Vec4V sinCoefficients1 = V4LoadA(g_PXSinCoefficients1.f); + const Vec4V sinCoefficients2 = V4LoadA(g_PXSinCoefficients2.f); + + const FloatV S1 = V4GetY(sinCoefficients0); + const FloatV S2 = V4GetZ(sinCoefficients0); + const FloatV S3 = V4GetW(sinCoefficients0); + const FloatV S4 = V4GetX(sinCoefficients1); + const FloatV S5 = V4GetY(sinCoefficients1); + const FloatV S6 = V4GetZ(sinCoefficients1); + const FloatV S7 = V4GetW(sinCoefficients1); + const FloatV S8 = V4GetX(sinCoefficients2); + const FloatV S9 = V4GetY(sinCoefficients2); + const FloatV S10 = V4GetZ(sinCoefficients2); + const FloatV S11 = V4GetW(sinCoefficients2); + + Vec3V Result; + Result = V3ScaleAdd(V3, S1, V1); + Result = V3ScaleAdd(V5, S2, Result); + Result = V3ScaleAdd(V7, S3, Result); + Result = V3ScaleAdd(V9, S4, Result); + Result = V3ScaleAdd(V11, S5, Result); + Result = V3ScaleAdd(V13, S6, Result); + Result = V3ScaleAdd(V15, S7, Result); + Result = V3ScaleAdd(V17, S8, Result); + Result = V3ScaleAdd(V19, S9, Result); + Result = V3ScaleAdd(V21, S10, Result); + Result = V3ScaleAdd(V23, S11, Result); + + ASSERT_ISVALIDVEC3V(Result); + return Result; +} + +PX_FORCE_INLINE Vec3V V3Cos(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + + // Modulo the range of the given angles such that -XM_2PI <= Angles < XM_2PI + const Vec4V recipTwoPi = V4LoadA(g_PXReciprocalTwoPi.f); + const Vec4V twoPi = V4LoadA(g_PXTwoPi.f); + const Vec3V tmp = V3Scale(a, recipTwoPi); + const Vec3V b = V3Round(tmp); + const Vec3V V1 = V3NegScaleSub(b, twoPi, a); + + // cos(V) ~= 1 - V^2 / 2! + V^4 / 4! - V^6 / 6! + V^8 / 8! - V^10 / 10! + V^12 / 12! - + // V^14 / 14! + V^16 / 16! - V^18 / 18! + V^20 / 20! - V^22 / 22! (for -PI <= V < PI) + const Vec3V V2 = V3Mul(V1, V1); + const Vec3V V4 = V3Mul(V2, V2); + const Vec3V V6 = V3Mul(V4, V2); + const Vec3V V8 = V3Mul(V4, V4); + const Vec3V V10 = V3Mul(V6, V4); + const Vec3V V12 = V3Mul(V6, V6); + const Vec3V V14 = V3Mul(V8, V6); + const Vec3V V16 = V3Mul(V8, V8); + const Vec3V V18 = V3Mul(V10, V8); + const Vec3V V20 = V3Mul(V10, V10); + const Vec3V V22 = V3Mul(V12, V10); + + const Vec4V cosCoefficients0 = V4LoadA(g_PXCosCoefficients0.f); + const Vec4V cosCoefficients1 = V4LoadA(g_PXCosCoefficients1.f); + const Vec4V cosCoefficients2 = V4LoadA(g_PXCosCoefficients2.f); + + const FloatV C1 = V4GetY(cosCoefficients0); + const FloatV C2 = V4GetZ(cosCoefficients0); + const FloatV C3 = V4GetW(cosCoefficients0); + const FloatV C4 = V4GetX(cosCoefficients1); + const FloatV C5 = V4GetY(cosCoefficients1); + const FloatV C6 = V4GetZ(cosCoefficients1); + const FloatV C7 = V4GetW(cosCoefficients1); + const FloatV C8 = V4GetX(cosCoefficients2); + const FloatV C9 = V4GetY(cosCoefficients2); + const FloatV C10 = V4GetZ(cosCoefficients2); + const FloatV C11 = V4GetW(cosCoefficients2); + + Vec3V Result; + Result = V3ScaleAdd(V2, C1, V3One()); + Result = V3ScaleAdd(V4, C2, Result); + Result = V3ScaleAdd(V6, C3, Result); + Result = V3ScaleAdd(V8, C4, Result); + Result = V3ScaleAdd(V10, C5, Result); + Result = V3ScaleAdd(V12, C6, Result); + Result = V3ScaleAdd(V14, C7, Result); + Result = V3ScaleAdd(V16, C8, Result); + Result = V3ScaleAdd(V18, C9, Result); + Result = V3ScaleAdd(V20, C10, Result); + Result = V3ScaleAdd(V22, C11, Result); + + ASSERT_ISVALIDVEC3V(Result); + return Result; +} + +PX_FORCE_INLINE Vec3V V3PermYZZ(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + return _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 2, 2, 1)); +} + +PX_FORCE_INLINE Vec3V V3PermXYX(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + return _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 0, 1, 0)); +} + +PX_FORCE_INLINE Vec3V V3PermYZX(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + return _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 0, 2, 1)); +} + +PX_FORCE_INLINE Vec3V V3PermZXY(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + return _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 1, 0, 2)); +} + +PX_FORCE_INLINE Vec3V V3PermZZY(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + return _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 1, 2, 2)); +} + +PX_FORCE_INLINE Vec3V V3PermYXX(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + return _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 0, 0, 1)); +} + +PX_FORCE_INLINE Vec3V V3Perm_Zero_1Z_0Y(const Vec3V v0, const Vec3V v1) +{ + ASSERT_ISVALIDVEC3V(v0); + ASSERT_ISVALIDVEC3V(v1); + return _mm_shuffle_ps(v1, v0, _MM_SHUFFLE(3, 1, 2, 3)); +} + +PX_FORCE_INLINE Vec3V V3Perm_0Z_Zero_1X(const Vec3V v0, const Vec3V v1) +{ + ASSERT_ISVALIDVEC3V(v0); + ASSERT_ISVALIDVEC3V(v1); + return _mm_shuffle_ps(v0, v1, _MM_SHUFFLE(3, 0, 3, 2)); +} + +PX_FORCE_INLINE Vec3V V3Perm_1Y_0X_Zero(const Vec3V v0, const Vec3V v1) +{ + ASSERT_ISVALIDVEC3V(v0); + ASSERT_ISVALIDVEC3V(v1); + // There must be a better way to do this. + Vec3V v2 = V3Zero(); + FloatV y1 = V3GetY(v1); + FloatV x0 = V3GetX(v0); + v2 = V3SetX(v2, y1); + return V3SetY(v2, x0); +} + +PX_FORCE_INLINE FloatV V3SumElems(const Vec3V a) +{ + ASSERT_ISVALIDVEC3V(a); + const __m128 shuf1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0)); // z,y,x,w + const __m128 shuf2 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 1, 1, 1)); // y,x,w,z + const __m128 shuf3 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2)); // x,w,z,y + return _mm_add_ps(_mm_add_ps(shuf1, shuf2), shuf3); +} + +PX_FORCE_INLINE PxU32 V3OutOfBounds(const Vec3V a, const Vec3V min, const Vec3V max) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(min); + ASSERT_ISVALIDVEC3V(max); + const BoolV c = BOr(V3IsGrtr(a, max), V3IsGrtr(min, a)); + return PxU32(!BAllEqFFFF(c)); +} + +PX_FORCE_INLINE PxU32 V3InBounds(const Vec3V a, const Vec3V min, const Vec3V max) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(min); + ASSERT_ISVALIDVEC3V(max); + const BoolV c = BAnd(V3IsGrtrOrEq(a, min), V3IsGrtrOrEq(max, a)); + return BAllEqTTTT(c); +} + +PX_FORCE_INLINE PxU32 V3OutOfBounds(const Vec3V a, const Vec3V bounds) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(bounds); + return V3OutOfBounds(a, V3Neg(bounds), bounds); +} + +PX_FORCE_INLINE PxU32 V3InBounds(const Vec3V a, const Vec3V bounds) +{ + ASSERT_ISVALIDVEC3V(a); + ASSERT_ISVALIDVEC3V(bounds); + return V3InBounds(a, V3Neg(bounds), bounds); +} + +PX_FORCE_INLINE void V3Transpose(Vec3V& col0, Vec3V& col1, Vec3V& col2) +{ + ASSERT_ISVALIDVEC3V(col0); + ASSERT_ISVALIDVEC3V(col1); + ASSERT_ISVALIDVEC3V(col2); + const Vec3V col3 = _mm_setzero_ps(); + Vec3V tmp0 = _mm_unpacklo_ps(col0, col1); + Vec3V tmp2 = _mm_unpacklo_ps(col2, col3); + Vec3V tmp1 = _mm_unpackhi_ps(col0, col1); + Vec3V tmp3 = _mm_unpackhi_ps(col2, col3); + col0 = _mm_movelh_ps(tmp0, tmp2); + col1 = _mm_movehl_ps(tmp2, tmp0); + col2 = _mm_movelh_ps(tmp1, tmp3); +} + +////////////////////////////////// +// VEC4V +////////////////////////////////// + +PX_FORCE_INLINE Vec4V V4Splat(const FloatV f) +{ + ASSERT_ISVALIDFLOATV(f); + // return _mm_shuffle_ps(f, f, _MM_SHUFFLE(0,0,0,0)); + return f; +} + +PX_FORCE_INLINE Vec4V V4Merge(const FloatV* const floatVArray) +{ + ASSERT_ISVALIDFLOATV(floatVArray[0]); + ASSERT_ISVALIDFLOATV(floatVArray[1]); + ASSERT_ISVALIDFLOATV(floatVArray[2]); + ASSERT_ISVALIDFLOATV(floatVArray[3]); + const __m128 xw = _mm_move_ss(floatVArray[1], floatVArray[0]); // y, y, y, x + const __m128 yz = _mm_move_ss(floatVArray[2], floatVArray[3]); // z, z, z, w + return _mm_shuffle_ps(xw, yz, _MM_SHUFFLE(0, 2, 1, 0)); +} + +PX_FORCE_INLINE Vec4V V4Merge(const FloatVArg x, const FloatVArg y, const FloatVArg z, const FloatVArg w) +{ + ASSERT_ISVALIDFLOATV(x); + ASSERT_ISVALIDFLOATV(y); + ASSERT_ISVALIDFLOATV(z); + ASSERT_ISVALIDFLOATV(w); + const __m128 xw = _mm_move_ss(y, x); // y, y, y, x + const __m128 yz = _mm_move_ss(z, w); // z, z, z, w + return _mm_shuffle_ps(xw, yz, _MM_SHUFFLE(0, 2, 1, 0)); +} + +PX_FORCE_INLINE Vec4V V4MergeW(const Vec4VArg x, const Vec4VArg y, const Vec4VArg z, const Vec4VArg w) +{ + const Vec4V xz = _mm_unpackhi_ps(x, z); + const Vec4V yw = _mm_unpackhi_ps(y, w); + return _mm_unpackhi_ps(xz, yw); +} + +PX_FORCE_INLINE Vec4V V4MergeZ(const Vec4VArg x, const Vec4VArg y, const Vec4VArg z, const Vec4VArg w) +{ + const Vec4V xz = _mm_unpackhi_ps(x, z); + const Vec4V yw = _mm_unpackhi_ps(y, w); + return _mm_unpacklo_ps(xz, yw); +} + +PX_FORCE_INLINE Vec4V V4MergeY(const Vec4VArg x, const Vec4VArg y, const Vec4VArg z, const Vec4VArg w) +{ + const Vec4V xz = _mm_unpacklo_ps(x, z); + const Vec4V yw = _mm_unpacklo_ps(y, w); + return _mm_unpackhi_ps(xz, yw); +} + +PX_FORCE_INLINE Vec4V V4MergeX(const Vec4VArg x, const Vec4VArg y, const Vec4VArg z, const Vec4VArg w) +{ + const Vec4V xz = _mm_unpacklo_ps(x, z); + const Vec4V yw = _mm_unpacklo_ps(y, w); + return _mm_unpacklo_ps(xz, yw); +} + +PX_FORCE_INLINE Vec4V V4UnpackXY(const Vec4VArg a, const Vec4VArg b) +{ + return _mm_unpacklo_ps(a, b); +} + +PX_FORCE_INLINE Vec4V V4UnpackZW(const Vec4VArg a, const Vec4VArg b) +{ + return _mm_unpackhi_ps(a, b); +} + +PX_FORCE_INLINE Vec4V V4PermYXWZ(const Vec4V a) +{ + return _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 3, 0, 1)); +} + +PX_FORCE_INLINE Vec4V V4PermXZXZ(const Vec4V a) +{ + return _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 0, 2, 0)); +} + +PX_FORCE_INLINE Vec4V V4PermYWYW(const Vec4V a) +{ + return _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 1, 3, 1)); +} + +PX_FORCE_INLINE Vec4V V4PermYZXW(const Vec4V a) +{ + return _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 0, 2, 1)); +} + +PX_FORCE_INLINE Vec4V V4PermZWXY(const Vec4V a) +{ + return _mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 0, 3, 2)); +} + +template +PX_FORCE_INLINE Vec4V V4Perm(const Vec4V a) +{ + return _mm_shuffle_ps(a, a, _MM_SHUFFLE(w, z, y, x)); +} + +PX_FORCE_INLINE Vec4V V4UnitW() +{ + const PX_ALIGN(16, PxF32 w[4]) = { 0.0f, 0.0f, 0.0f, 1.0f }; + const __m128 w128 = _mm_load_ps(w); + return w128; +} + +PX_FORCE_INLINE Vec4V V4UnitX() +{ + const PX_ALIGN(16, PxF32 x[4]) = { 1.0f, 0.0f, 0.0f, 0.0f }; + const __m128 x128 = _mm_load_ps(x); + return x128; +} + +PX_FORCE_INLINE Vec4V V4UnitY() +{ + const PX_ALIGN(16, PxF32 y[4]) = { 0.0f, 1.0f, 0.0f, 0.0f }; + const __m128 y128 = _mm_load_ps(y); + return y128; +} + +PX_FORCE_INLINE Vec4V V4UnitZ() +{ + const PX_ALIGN(16, PxF32 z[4]) = { 0.0f, 0.0f, 1.0f, 0.0f }; + const __m128 z128 = _mm_load_ps(z); + return z128; +} + +PX_FORCE_INLINE FloatV V4GetW(const Vec4V f) +{ + return _mm_shuffle_ps(f, f, _MM_SHUFFLE(3, 3, 3, 3)); +} + +PX_FORCE_INLINE FloatV V4GetX(const Vec4V f) +{ + return _mm_shuffle_ps(f, f, _MM_SHUFFLE(0, 0, 0, 0)); +} + +PX_FORCE_INLINE FloatV V4GetY(const Vec4V f) +{ + return _mm_shuffle_ps(f, f, _MM_SHUFFLE(1, 1, 1, 1)); +} + +PX_FORCE_INLINE FloatV V4GetZ(const Vec4V f) +{ + return _mm_shuffle_ps(f, f, _MM_SHUFFLE(2, 2, 2, 2)); +} + +PX_FORCE_INLINE Vec4V V4SetW(const Vec4V v, const FloatV f) +{ + ASSERT_ISVALIDFLOATV(f); + return V4Sel(BTTTF(), v, f); +} + +PX_FORCE_INLINE Vec4V V4ClearW(const Vec4V v) +{ + return _mm_and_ps(v, (VecI32V&)internalWindowsSimd::gMaskXYZ); +} + +PX_FORCE_INLINE Vec4V V4SetX(const Vec4V v, const FloatV f) +{ + ASSERT_ISVALIDFLOATV(f); + return V4Sel(BFTTT(), v, f); +} + +PX_FORCE_INLINE Vec4V V4SetY(const Vec4V v, const FloatV f) +{ + ASSERT_ISVALIDFLOATV(f); + return V4Sel(BTFTT(), v, f); +} + +PX_FORCE_INLINE Vec4V V4SetZ(const Vec4V v, const FloatV f) +{ + ASSERT_ISVALIDFLOATV(f); + return V4Sel(BTTFT(), v, f); +} + +PX_FORCE_INLINE Vec4V V4Zero() +{ + return _mm_setzero_ps(); +} + +PX_FORCE_INLINE Vec4V V4One() +{ + return V4Load(1.0f); +} + +PX_FORCE_INLINE Vec4V V4Eps() +{ + return V4Load(PX_EPS_REAL); +} + +PX_FORCE_INLINE Vec4V V4Neg(const Vec4V f) +{ + return _mm_sub_ps(_mm_setzero_ps(), f); +} + +PX_FORCE_INLINE Vec4V V4Add(const Vec4V a, const Vec4V b) +{ + return _mm_add_ps(a, b); +} + +PX_FORCE_INLINE Vec4V V4Sub(const Vec4V a, const Vec4V b) +{ + return _mm_sub_ps(a, b); +} + +PX_FORCE_INLINE Vec4V V4Scale(const Vec4V a, const FloatV b) +{ + return _mm_mul_ps(a, b); +} + +PX_FORCE_INLINE Vec4V V4Mul(const Vec4V a, const Vec4V b) +{ + return _mm_mul_ps(a, b); +} + +PX_FORCE_INLINE Vec4V V4ScaleInv(const Vec4V a, const FloatV b) +{ + ASSERT_ISVALIDFLOATV(b); + return _mm_div_ps(a, b); +} + +PX_FORCE_INLINE Vec4V V4Div(const Vec4V a, const Vec4V b) +{ + return _mm_div_ps(a, b); +} + +PX_FORCE_INLINE Vec4V V4ScaleInvFast(const Vec4V a, const FloatV b) +{ + ASSERT_ISVALIDFLOATV(b); + return _mm_mul_ps(a, _mm_rcp_ps(b)); +} + +PX_FORCE_INLINE Vec4V V4DivFast(const Vec4V a, const Vec4V b) +{ + return _mm_mul_ps(a, _mm_rcp_ps(b)); +} + +PX_FORCE_INLINE Vec4V V4Recip(const Vec4V a) +{ + return _mm_div_ps(V4One(), a); +} + +PX_FORCE_INLINE Vec4V V4RecipFast(const Vec4V a) +{ + return _mm_rcp_ps(a); +} + +PX_FORCE_INLINE Vec4V V4Rsqrt(const Vec4V a) +{ + return _mm_div_ps(V4One(), _mm_sqrt_ps(a)); +} + +PX_FORCE_INLINE Vec4V V4RsqrtFast(const Vec4V a) +{ + return _mm_rsqrt_ps(a); +} + +PX_FORCE_INLINE Vec4V V4Sqrt(const Vec4V a) +{ + return _mm_sqrt_ps(a); +} + +PX_FORCE_INLINE Vec4V V4ScaleAdd(const Vec4V a, const FloatV b, const Vec4V c) +{ + ASSERT_ISVALIDFLOATV(b); + return V4Add(V4Scale(a, b), c); +} + +PX_FORCE_INLINE Vec4V V4NegScaleSub(const Vec4V a, const FloatV b, const Vec4V c) +{ + ASSERT_ISVALIDFLOATV(b); + return V4Sub(c, V4Scale(a, b)); +} + +PX_FORCE_INLINE Vec4V V4MulAdd(const Vec4V a, const Vec4V b, const Vec4V c) +{ + return V4Add(V4Mul(a, b), c); +} + +PX_FORCE_INLINE Vec4V V4NegMulSub(const Vec4V a, const Vec4V b, const Vec4V c) +{ + return V4Sub(c, V4Mul(a, b)); +} + +PX_FORCE_INLINE Vec4V V4Abs(const Vec4V a) +{ + return V4Max(a, V4Neg(a)); +} + +PX_FORCE_INLINE FloatV V4SumElements(const Vec4V a) +{ + const Vec4V xy = V4UnpackXY(a, a); // x,x,y,y + const Vec4V zw = V4UnpackZW(a, a); // z,z,w,w + const Vec4V xz_yw = V4Add(xy, zw); // x+z,x+z,y+w,y+w + const FloatV xz = V4GetX(xz_yw); // x+z + const FloatV yw = V4GetZ(xz_yw); // y+w + return FAdd(xz, yw); // sum +} + +PX_FORCE_INLINE FloatV V4Dot(const Vec4V a, const Vec4V b) +{ + const __m128 dot1 = _mm_mul_ps(a, b); // x,y,z,w + const __m128 shuf1 = _mm_shuffle_ps(dot1, dot1, _MM_SHUFFLE(2, 1, 0, 3)); // w,x,y,z + const __m128 shuf2 = _mm_shuffle_ps(dot1, dot1, _MM_SHUFFLE(1, 0, 3, 2)); // z,w,x,y + const __m128 shuf3 = _mm_shuffle_ps(dot1, dot1, _MM_SHUFFLE(0, 3, 2, 1)); // y,z,w,x + return _mm_add_ps(_mm_add_ps(shuf2, shuf3), _mm_add_ps(dot1, shuf1)); + + // PT: this version has two less instructions but we should check its accuracy + // aw*bw | az*bz | ay*by | ax*bx + // const __m128 t0 = _mm_mul_ps(a, b); + // ay*by | ax*bx | aw*bw | az*bz + // const __m128 t1 = _mm_shuffle_ps(t0, t0, _MM_SHUFFLE(1,0,3,2)); + // ay*by + aw*bw | ax*bx + az*bz | aw*bw + ay*by | az*bz + ax*bx + // const __m128 t2 = _mm_add_ps(t0, t1); + // ax*bx + az*bz | ay*by + aw*bw | az*bz + ax*bx | aw*bw + ay*by + // const __m128 t3 = _mm_shuffle_ps(t2, t2, _MM_SHUFFLE(2,3,0,1)); + // ax*bx + az*bz + ay*by + aw*bw + // return _mm_add_ps(t3, t2); + // ay*by + aw*bw + ax*bx + az*bz + // az*bz + ax*bx + aw*bw + ay*by + // aw*bw + ay*by + az*bz + ax*bx +} + +PX_FORCE_INLINE FloatV V4Dot3(const Vec4V a, const Vec4V b) +{ + const __m128 dot1 = _mm_mul_ps(a, b); // aw*bw | az*bz | ay*by | ax*bx + const __m128 shuf1 = _mm_shuffle_ps(dot1, dot1, _MM_SHUFFLE(0, 0, 0, 0)); // ax*bx | ax*bx | ax*bx | ax*bx + const __m128 shuf2 = _mm_shuffle_ps(dot1, dot1, _MM_SHUFFLE(1, 1, 1, 1)); // ay*by | ay*by | ay*by | ay*by + const __m128 shuf3 = _mm_shuffle_ps(dot1, dot1, _MM_SHUFFLE(2, 2, 2, 2)); // az*bz | az*bz | az*bz | az*bz + return _mm_add_ps(_mm_add_ps(shuf1, shuf2), shuf3); // ax*bx + ay*by + az*bz in each component +} + +PX_FORCE_INLINE Vec4V V4Cross(const Vec4V a, const Vec4V b) +{ + const __m128 r1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 1, 0, 2)); // z,x,y,w + const __m128 r2 = _mm_shuffle_ps(b, b, _MM_SHUFFLE(3, 0, 2, 1)); // y,z,x,w + const __m128 l1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 0, 2, 1)); // y,z,x,w + const __m128 l2 = _mm_shuffle_ps(b, b, _MM_SHUFFLE(3, 1, 0, 2)); // z,x,y,w + return _mm_sub_ps(_mm_mul_ps(l1, l2), _mm_mul_ps(r1, r2)); +} + +PX_FORCE_INLINE FloatV V4Length(const Vec4V a) +{ + return _mm_sqrt_ps(V4Dot(a, a)); +} + +PX_FORCE_INLINE FloatV V4LengthSq(const Vec4V a) +{ + return V4Dot(a, a); +} + +PX_FORCE_INLINE Vec4V V4Normalize(const Vec4V a) +{ + ASSERT_ISFINITELENGTH(a); + return V4ScaleInv(a, _mm_sqrt_ps(V4Dot(a, a))); +} + +PX_FORCE_INLINE Vec4V V4NormalizeFast(const Vec4V a) +{ + ASSERT_ISFINITELENGTH(a); + return V4ScaleInvFast(a, _mm_sqrt_ps(V4Dot(a, a))); +} + +PX_FORCE_INLINE Vec4V V4NormalizeSafe(const Vec4V a, const Vec4V unsafeReturnValue) +{ + const __m128 eps = V3Eps(); + const __m128 length = V4Length(a); + const __m128 isGreaterThanZero = V4IsGrtr(length, eps); + return V4Sel(isGreaterThanZero, V4ScaleInv(a, length), unsafeReturnValue); +} + +PX_FORCE_INLINE Vec4V V4Sel(const BoolV c, const Vec4V a, const Vec4V b) +{ + return _mm_or_ps(_mm_andnot_ps(c, b), _mm_and_ps(c, a)); +} + +PX_FORCE_INLINE BoolV V4IsGrtr(const Vec4V a, const Vec4V b) +{ + return _mm_cmpgt_ps(a, b); +} + +PX_FORCE_INLINE BoolV V4IsGrtrOrEq(const Vec4V a, const Vec4V b) +{ + return _mm_cmpge_ps(a, b); +} + +PX_FORCE_INLINE BoolV V4IsEq(const Vec4V a, const Vec4V b) +{ + return _mm_cmpeq_ps(a, b); +} + +PX_FORCE_INLINE BoolV V4IsEqU32(const VecU32V a, const VecU32V b) +{ + return internalWindowsSimd::m128_I2F( + _mm_cmpeq_epi32(internalWindowsSimd::m128_F2I(a), internalWindowsSimd::m128_F2I(b))); +} + +PX_FORCE_INLINE Vec4V V4Max(const Vec4V a, const Vec4V b) +{ + return _mm_max_ps(a, b); +} + +PX_FORCE_INLINE Vec4V V4Min(const Vec4V a, const Vec4V b) +{ + return _mm_min_ps(a, b); +} + +PX_FORCE_INLINE FloatV V4ExtractMax(const Vec4V a) +{ + const __m128 shuf1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 1, 0, 3)); + const __m128 shuf2 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 0, 3, 2)); + const __m128 shuf3 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 3, 2, 1)); + + return _mm_max_ps(_mm_max_ps(a, shuf1), _mm_max_ps(shuf2, shuf3)); +} + +PX_FORCE_INLINE FloatV V4ExtractMin(const Vec4V a) +{ + const __m128 shuf1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 1, 0, 3)); + const __m128 shuf2 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 0, 3, 2)); + const __m128 shuf3 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 3, 2, 1)); + + return _mm_min_ps(_mm_min_ps(a, shuf1), _mm_min_ps(shuf2, shuf3)); +} + +PX_FORCE_INLINE Vec4V V4Clamp(const Vec4V a, const Vec4V minV, const Vec4V maxV) +{ + return V4Max(V4Min(a, maxV), minV); +} + +PX_FORCE_INLINE PxU32 V4AllGrtr(const Vec4V a, const Vec4V b) +{ + return internalWindowsSimd::BAllTrue4_R(V4IsGrtr(a, b)); +} + +PX_FORCE_INLINE PxU32 V4AllGrtrOrEq(const Vec4V a, const Vec4V b) +{ + return internalWindowsSimd::BAllTrue4_R(V4IsGrtrOrEq(a, b)); +} + +PX_FORCE_INLINE PxU32 V4AllGrtrOrEq3(const Vec4V a, const Vec4V b) +{ + return internalWindowsSimd::BAllTrue3_R(V4IsGrtrOrEq(a, b)); +} + +PX_FORCE_INLINE PxU32 V4AllEq(const Vec4V a, const Vec4V b) +{ + return internalWindowsSimd::BAllTrue4_R(V4IsEq(a, b)); +} + +PX_FORCE_INLINE PxU32 V4AnyGrtr3(const Vec4V a, const Vec4V b) +{ + return internalWindowsSimd::BAnyTrue3_R(V4IsGrtr(a, b)); +} + +PX_FORCE_INLINE Vec4V V4Round(const Vec4V a) +{ + // return _mm_round_ps(a, 0x0); + const Vec4V half = V4Load(0.5f); + const __m128 signBit = _mm_cvtepi32_ps(_mm_srli_epi32(_mm_cvtps_epi32(a), 31)); + const Vec4V aRound = V4Sub(V4Add(a, half), signBit); + const __m128i tmp = _mm_cvttps_epi32(aRound); + return _mm_cvtepi32_ps(tmp); +} + +PX_FORCE_INLINE Vec4V V4Sin(const Vec4V a) +{ + const Vec4V recipTwoPi = V4LoadA(g_PXReciprocalTwoPi.f); + const Vec4V twoPi = V4LoadA(g_PXTwoPi.f); + const Vec4V tmp = V4Mul(a, recipTwoPi); + const Vec4V b = V4Round(tmp); + const Vec4V V1 = V4NegMulSub(twoPi, b, a); + + // sin(V) ~= V - V^3 / 3! + V^5 / 5! - V^7 / 7! + V^9 / 9! - V^11 / 11! + V^13 / 13! - + // V^15 / 15! + V^17 / 17! - V^19 / 19! + V^21 / 21! - V^23 / 23! (for -PI <= V < PI) + const Vec4V V2 = V4Mul(V1, V1); + const Vec4V V3 = V4Mul(V2, V1); + const Vec4V V5 = V4Mul(V3, V2); + const Vec4V V7 = V4Mul(V5, V2); + const Vec4V V9 = V4Mul(V7, V2); + const Vec4V V11 = V4Mul(V9, V2); + const Vec4V V13 = V4Mul(V11, V2); + const Vec4V V15 = V4Mul(V13, V2); + const Vec4V V17 = V4Mul(V15, V2); + const Vec4V V19 = V4Mul(V17, V2); + const Vec4V V21 = V4Mul(V19, V2); + const Vec4V V23 = V4Mul(V21, V2); + + const Vec4V sinCoefficients0 = V4LoadA(g_PXSinCoefficients0.f); + const Vec4V sinCoefficients1 = V4LoadA(g_PXSinCoefficients1.f); + const Vec4V sinCoefficients2 = V4LoadA(g_PXSinCoefficients2.f); + + const FloatV S1 = V4GetY(sinCoefficients0); + const FloatV S2 = V4GetZ(sinCoefficients0); + const FloatV S3 = V4GetW(sinCoefficients0); + const FloatV S4 = V4GetX(sinCoefficients1); + const FloatV S5 = V4GetY(sinCoefficients1); + const FloatV S6 = V4GetZ(sinCoefficients1); + const FloatV S7 = V4GetW(sinCoefficients1); + const FloatV S8 = V4GetX(sinCoefficients2); + const FloatV S9 = V4GetY(sinCoefficients2); + const FloatV S10 = V4GetZ(sinCoefficients2); + const FloatV S11 = V4GetW(sinCoefficients2); + + Vec4V Result; + Result = V4MulAdd(S1, V3, V1); + Result = V4MulAdd(S2, V5, Result); + Result = V4MulAdd(S3, V7, Result); + Result = V4MulAdd(S4, V9, Result); + Result = V4MulAdd(S5, V11, Result); + Result = V4MulAdd(S6, V13, Result); + Result = V4MulAdd(S7, V15, Result); + Result = V4MulAdd(S8, V17, Result); + Result = V4MulAdd(S9, V19, Result); + Result = V4MulAdd(S10, V21, Result); + Result = V4MulAdd(S11, V23, Result); + + return Result; +} + +PX_FORCE_INLINE Vec4V V4Cos(const Vec4V a) +{ + const Vec4V recipTwoPi = V4LoadA(g_PXReciprocalTwoPi.f); + const FloatV twoPi = V4LoadA(g_PXTwoPi.f); + const Vec4V tmp = V4Mul(a, recipTwoPi); + const Vec4V b = V4Round(tmp); + const Vec4V V1 = V4NegMulSub(twoPi, b, a); + + // cos(V) ~= 1 - V^2 / 2! + V^4 / 4! - V^6 / 6! + V^8 / 8! - V^10 / 10! + V^12 / 12! - + // V^14 / 14! + V^16 / 16! - V^18 / 18! + V^20 / 20! - V^22 / 22! (for -PI <= V < PI) + const Vec4V V2 = V4Mul(V1, V1); + const Vec4V V4 = V4Mul(V2, V2); + const Vec4V V6 = V4Mul(V4, V2); + const Vec4V V8 = V4Mul(V4, V4); + const Vec4V V10 = V4Mul(V6, V4); + const Vec4V V12 = V4Mul(V6, V6); + const Vec4V V14 = V4Mul(V8, V6); + const Vec4V V16 = V4Mul(V8, V8); + const Vec4V V18 = V4Mul(V10, V8); + const Vec4V V20 = V4Mul(V10, V10); + const Vec4V V22 = V4Mul(V12, V10); + + const Vec4V cosCoefficients0 = V4LoadA(g_PXCosCoefficients0.f); + const Vec4V cosCoefficients1 = V4LoadA(g_PXCosCoefficients1.f); + const Vec4V cosCoefficients2 = V4LoadA(g_PXCosCoefficients2.f); + + const FloatV C1 = V4GetY(cosCoefficients0); + const FloatV C2 = V4GetZ(cosCoefficients0); + const FloatV C3 = V4GetW(cosCoefficients0); + const FloatV C4 = V4GetX(cosCoefficients1); + const FloatV C5 = V4GetY(cosCoefficients1); + const FloatV C6 = V4GetZ(cosCoefficients1); + const FloatV C7 = V4GetW(cosCoefficients1); + const FloatV C8 = V4GetX(cosCoefficients2); + const FloatV C9 = V4GetY(cosCoefficients2); + const FloatV C10 = V4GetZ(cosCoefficients2); + const FloatV C11 = V4GetW(cosCoefficients2); + + Vec4V Result; + Result = V4MulAdd(C1, V2, V4One()); + Result = V4MulAdd(C2, V4, Result); + Result = V4MulAdd(C3, V6, Result); + Result = V4MulAdd(C4, V8, Result); + Result = V4MulAdd(C5, V10, Result); + Result = V4MulAdd(C6, V12, Result); + Result = V4MulAdd(C7, V14, Result); + Result = V4MulAdd(C8, V16, Result); + Result = V4MulAdd(C9, V18, Result); + Result = V4MulAdd(C10, V20, Result); + Result = V4MulAdd(C11, V22, Result); + + return Result; +} + +PX_FORCE_INLINE void V4Transpose(Vec4V& col0, Vec4V& col1, Vec4V& col2, Vec4V& col3) +{ + Vec4V tmp0 = _mm_unpacklo_ps(col0, col1); + Vec4V tmp2 = _mm_unpacklo_ps(col2, col3); + Vec4V tmp1 = _mm_unpackhi_ps(col0, col1); + Vec4V tmp3 = _mm_unpackhi_ps(col2, col3); + col0 = _mm_movelh_ps(tmp0, tmp2); + col1 = _mm_movehl_ps(tmp2, tmp0); + col2 = _mm_movelh_ps(tmp1, tmp3); + col3 = _mm_movehl_ps(tmp3, tmp1); +} + +////////////////////////////////// +// BoolV +////////////////////////////////// + +PX_FORCE_INLINE BoolV BFFFF() +{ + return _mm_setzero_ps(); +} + +PX_FORCE_INLINE BoolV BFFFT() +{ + /*const PX_ALIGN(16, PxU32 f[4])={0,0,0,0xFFFFFFFF}; + const __m128 ffft=_mm_load_ps((float*)&f); + return ffft;*/ + return internalWindowsSimd::m128_I2F(_mm_set_epi32(-1, 0, 0, 0)); +} + +PX_FORCE_INLINE BoolV BFFTF() +{ + /*const PX_ALIGN(16, PxU32 f[4])={0,0,0xFFFFFFFF,0}; + const __m128 fftf=_mm_load_ps((float*)&f); + return fftf;*/ + return internalWindowsSimd::m128_I2F(_mm_set_epi32(0, -1, 0, 0)); +} + +PX_FORCE_INLINE BoolV BFFTT() +{ + /*const PX_ALIGN(16, PxU32 f[4])={0,0,0xFFFFFFFF,0xFFFFFFFF}; + const __m128 fftt=_mm_load_ps((float*)&f); + return fftt;*/ + return internalWindowsSimd::m128_I2F(_mm_set_epi32(-1, -1, 0, 0)); +} + +PX_FORCE_INLINE BoolV BFTFF() +{ + /*const PX_ALIGN(16, PxU32 f[4])={0,0xFFFFFFFF,0,0}; + const __m128 ftff=_mm_load_ps((float*)&f); + return ftff;*/ + return internalWindowsSimd::m128_I2F(_mm_set_epi32(0, 0, -1, 0)); +} + +PX_FORCE_INLINE BoolV BFTFT() +{ + /*const PX_ALIGN(16, PxU32 f[4])={0,0xFFFFFFFF,0,0xFFFFFFFF}; + const __m128 ftft=_mm_load_ps((float*)&f); + return ftft;*/ + return internalWindowsSimd::m128_I2F(_mm_set_epi32(-1, 0, -1, 0)); +} + +PX_FORCE_INLINE BoolV BFTTF() +{ + /*const PX_ALIGN(16, PxU32 f[4])={0,0xFFFFFFFF,0xFFFFFFFF,0}; + const __m128 fttf=_mm_load_ps((float*)&f); + return fttf;*/ + return internalWindowsSimd::m128_I2F(_mm_set_epi32(0, -1, -1, 0)); +} + +PX_FORCE_INLINE BoolV BFTTT() +{ + /*const PX_ALIGN(16, PxU32 f[4])={0,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF}; + const __m128 fttt=_mm_load_ps((float*)&f); + return fttt;*/ + return internalWindowsSimd::m128_I2F(_mm_set_epi32(-1, -1, -1, 0)); +} + +PX_FORCE_INLINE BoolV BTFFF() +{ + // const PX_ALIGN(16, PxU32 f[4])={0xFFFFFFFF,0,0,0}; + // const __m128 tfff=_mm_load_ps((float*)&f); + // return tfff; + return internalWindowsSimd::m128_I2F(_mm_set_epi32(0, 0, 0, -1)); +} + +PX_FORCE_INLINE BoolV BTFFT() +{ + /*const PX_ALIGN(16, PxU32 f[4])={0xFFFFFFFF,0,0,0xFFFFFFFF}; + const __m128 tfft=_mm_load_ps((float*)&f); + return tfft;*/ + return internalWindowsSimd::m128_I2F(_mm_set_epi32(-1, 0, 0, -1)); +} + +PX_FORCE_INLINE BoolV BTFTF() +{ + /*const PX_ALIGN(16, PxU32 f[4])={0xFFFFFFFF,0,0xFFFFFFFF,0}; + const __m128 tftf=_mm_load_ps((float*)&f); + return tftf;*/ + return internalWindowsSimd::m128_I2F(_mm_set_epi32(0, -1, 0, -1)); +} + +PX_FORCE_INLINE BoolV BTFTT() +{ + /*const PX_ALIGN(16, PxU32 f[4])={0xFFFFFFFF,0,0xFFFFFFFF,0xFFFFFFFF}; + const __m128 tftt=_mm_load_ps((float*)&f); + return tftt;*/ + return internalWindowsSimd::m128_I2F(_mm_set_epi32(-1, -1, 0, -1)); +} + +PX_FORCE_INLINE BoolV BTTFF() +{ + /*const PX_ALIGN(16, PxU32 f[4])={0xFFFFFFFF,0xFFFFFFFF,0,0}; + const __m128 ttff=_mm_load_ps((float*)&f); + return ttff;*/ + return internalWindowsSimd::m128_I2F(_mm_set_epi32(0, 0, -1, -1)); +} + +PX_FORCE_INLINE BoolV BTTFT() +{ + /*const PX_ALIGN(16, PxU32 f[4])={0xFFFFFFFF,0xFFFFFFFF,0,0xFFFFFFFF}; + const __m128 ttft=_mm_load_ps((float*)&f); + return ttft;*/ + return internalWindowsSimd::m128_I2F(_mm_set_epi32(-1, 0, -1, -1)); +} + +PX_FORCE_INLINE BoolV BTTTF() +{ + /*const PX_ALIGN(16, PxU32 f[4])={0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0}; + const __m128 tttf=_mm_load_ps((float*)&f); + return tttf;*/ + return internalWindowsSimd::m128_I2F(_mm_set_epi32(0, -1, -1, -1)); +} + +PX_FORCE_INLINE BoolV BTTTT() +{ + /*const PX_ALIGN(16, PxU32 f[4])={0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF}; + const __m128 tttt=_mm_load_ps((float*)&f); + return tttt;*/ + return internalWindowsSimd::m128_I2F(_mm_set_epi32(-1, -1, -1, -1)); +} + +PX_FORCE_INLINE BoolV BXMask() +{ + /*const PX_ALIGN(16, PxU32 f[4])={0xFFFFFFFF,0,0,0}; + const __m128 tfff=_mm_load_ps((float*)&f); + return tfff;*/ + return internalWindowsSimd::m128_I2F(_mm_set_epi32(0, 0, 0, -1)); +} + +PX_FORCE_INLINE BoolV BYMask() +{ + /*const PX_ALIGN(16, PxU32 f[4])={0,0xFFFFFFFF,0,0}; + const __m128 ftff=_mm_load_ps((float*)&f); + return ftff;*/ + return internalWindowsSimd::m128_I2F(_mm_set_epi32(0, 0, -1, 0)); +} + +PX_FORCE_INLINE BoolV BZMask() +{ + /*const PX_ALIGN(16, PxU32 f[4])={0,0,0xFFFFFFFF,0}; + const __m128 fftf=_mm_load_ps((float*)&f); + return fftf;*/ + return internalWindowsSimd::m128_I2F(_mm_set_epi32(0, -1, 0, 0)); +} + +PX_FORCE_INLINE BoolV BWMask() +{ + /*const PX_ALIGN(16, PxU32 f[4])={0,0,0,0xFFFFFFFF}; + const __m128 ffft=_mm_load_ps((float*)&f); + return ffft;*/ + return internalWindowsSimd::m128_I2F(_mm_set_epi32(-1, 0, 0, 0)); +} + +PX_FORCE_INLINE BoolV BGetX(const BoolV f) +{ + return _mm_shuffle_ps(f, f, _MM_SHUFFLE(0, 0, 0, 0)); +} + +PX_FORCE_INLINE BoolV BGetY(const BoolV f) +{ + return _mm_shuffle_ps(f, f, _MM_SHUFFLE(1, 1, 1, 1)); +} + +PX_FORCE_INLINE BoolV BGetZ(const BoolV f) +{ + return _mm_shuffle_ps(f, f, _MM_SHUFFLE(2, 2, 2, 2)); +} + +PX_FORCE_INLINE BoolV BGetW(const BoolV f) +{ + return _mm_shuffle_ps(f, f, _MM_SHUFFLE(3, 3, 3, 3)); +} + +PX_FORCE_INLINE BoolV BSetX(const BoolV v, const BoolV f) +{ + return V4Sel(BFTTT(), v, f); +} + +PX_FORCE_INLINE BoolV BSetY(const BoolV v, const BoolV f) +{ + return V4Sel(BTFTT(), v, f); +} + +PX_FORCE_INLINE BoolV BSetZ(const BoolV v, const BoolV f) +{ + return V4Sel(BTTFT(), v, f); +} + +PX_FORCE_INLINE BoolV BSetW(const BoolV v, const BoolV f) +{ + return V4Sel(BTTTF(), v, f); +} + +template +BoolV BSplatElement(BoolV a) +{ + return internalWindowsSimd::m128_I2F( + _mm_shuffle_epi32(internalWindowsSimd::m128_F2I(a), _MM_SHUFFLE(index, index, index, index))); +} + +PX_FORCE_INLINE BoolV BAnd(const BoolV a, const BoolV b) +{ + return _mm_and_ps(a, b); +} + +PX_FORCE_INLINE BoolV BNot(const BoolV a) +{ + const BoolV bAllTrue(BTTTT()); + return _mm_xor_ps(a, bAllTrue); +} + +PX_FORCE_INLINE BoolV BAndNot(const BoolV a, const BoolV b) +{ + return _mm_andnot_ps(b, a); +} + +PX_FORCE_INLINE BoolV BOr(const BoolV a, const BoolV b) +{ + return _mm_or_ps(a, b); +} + +PX_FORCE_INLINE BoolV BAllTrue4(const BoolV a) +{ + const BoolV bTmp = + _mm_and_ps(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 1, 0, 1)), _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 3, 2, 3))); + return _mm_and_ps(_mm_shuffle_ps(bTmp, bTmp, _MM_SHUFFLE(0, 0, 0, 0)), + _mm_shuffle_ps(bTmp, bTmp, _MM_SHUFFLE(1, 1, 1, 1))); +} + +PX_FORCE_INLINE BoolV BAnyTrue4(const BoolV a) +{ + const BoolV bTmp = + _mm_or_ps(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 1, 0, 1)), _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 3, 2, 3))); + return _mm_or_ps(_mm_shuffle_ps(bTmp, bTmp, _MM_SHUFFLE(0, 0, 0, 0)), + _mm_shuffle_ps(bTmp, bTmp, _MM_SHUFFLE(1, 1, 1, 1))); +} + +PX_FORCE_INLINE BoolV BAllTrue3(const BoolV a) +{ + const BoolV bTmp = + _mm_and_ps(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 1, 0, 1)), _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2))); + return _mm_and_ps(_mm_shuffle_ps(bTmp, bTmp, _MM_SHUFFLE(0, 0, 0, 0)), + _mm_shuffle_ps(bTmp, bTmp, _MM_SHUFFLE(1, 1, 1, 1))); +} + +PX_FORCE_INLINE BoolV BAnyTrue3(const BoolV a) +{ + const BoolV bTmp = + _mm_or_ps(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 1, 0, 1)), _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2))); + return _mm_or_ps(_mm_shuffle_ps(bTmp, bTmp, _MM_SHUFFLE(0, 0, 0, 0)), + _mm_shuffle_ps(bTmp, bTmp, _MM_SHUFFLE(1, 1, 1, 1))); +} + +PX_FORCE_INLINE PxU32 BAllEq(const BoolV a, const BoolV b) +{ + const BoolV bTest = internalWindowsSimd::m128_I2F( + _mm_cmpeq_epi32(internalWindowsSimd::m128_F2I(a), internalWindowsSimd::m128_F2I(b))); + return internalWindowsSimd::BAllTrue4_R(bTest); +} + +PX_FORCE_INLINE PxU32 BAllEqTTTT(const BoolV a) +{ + return PxU32(_mm_movemask_ps(a)==15); +} + +PX_FORCE_INLINE PxU32 BAllEqFFFF(const BoolV a) +{ + return PxU32(_mm_movemask_ps(a)==0); +} + +PX_FORCE_INLINE PxU32 BGetBitMask(const BoolV a) +{ + return PxU32(_mm_movemask_ps(a)); +} + +////////////////////////////////// +// MAT33V +////////////////////////////////// + +PX_FORCE_INLINE Vec3V M33MulV3(const Mat33V& a, const Vec3V b) +{ + const FloatV x = V3GetX(b); + const FloatV y = V3GetY(b); + const FloatV z = V3GetZ(b); + const Vec3V v0 = V3Scale(a.col0, x); + const Vec3V v1 = V3Scale(a.col1, y); + const Vec3V v2 = V3Scale(a.col2, z); + const Vec3V v0PlusV1 = V3Add(v0, v1); + return V3Add(v0PlusV1, v2); +} + +PX_FORCE_INLINE Vec3V M33TrnspsMulV3(const Mat33V& a, const Vec3V b) +{ + Vec3V v0 = V3Mul(a.col0, b); + Vec3V v1 = V3Mul(a.col1, b); + Vec3V v2 = V3Mul(a.col2, b); + V3Transpose(v0, v1, v2); + return V3Add(V3Add(v0, v1), v2); +} + +PX_FORCE_INLINE Vec3V M33MulV3AddV3(const Mat33V& A, const Vec3V b, const Vec3V c) +{ + const FloatV x = V3GetX(b); + const FloatV y = V3GetY(b); + const FloatV z = V3GetZ(b); + Vec3V result = V3ScaleAdd(A.col0, x, c); + result = V3ScaleAdd(A.col1, y, result); + return V3ScaleAdd(A.col2, z, result); +} + +PX_FORCE_INLINE Mat33V M33MulM33(const Mat33V& a, const Mat33V& b) +{ + return Mat33V(M33MulV3(a, b.col0), M33MulV3(a, b.col1), M33MulV3(a, b.col2)); +} + +PX_FORCE_INLINE Mat33V M33Add(const Mat33V& a, const Mat33V& b) +{ + return Mat33V(V3Add(a.col0, b.col0), V3Add(a.col1, b.col1), V3Add(a.col2, b.col2)); +} + +PX_FORCE_INLINE Mat33V M33Scale(const Mat33V& a, const FloatV& b) +{ + return Mat33V(V3Scale(a.col0, b), V3Scale(a.col1, b), V3Scale(a.col2, b)); +} + +PX_FORCE_INLINE Mat33V M33Sub(const Mat33V& a, const Mat33V& b) +{ + return Mat33V(V3Sub(a.col0, b.col0), V3Sub(a.col1, b.col1), V3Sub(a.col2, b.col2)); +} + +PX_FORCE_INLINE Mat33V M33Neg(const Mat33V& a) +{ + return Mat33V(V3Neg(a.col0), V3Neg(a.col1), V3Neg(a.col2)); +} + +PX_FORCE_INLINE Mat33V M33Abs(const Mat33V& a) +{ + return Mat33V(V3Abs(a.col0), V3Abs(a.col1), V3Abs(a.col2)); +} + +PX_FORCE_INLINE Mat33V M33Inverse(const Mat33V& a) +{ + const BoolV tfft = BTFFT(); + const BoolV tttf = BTTTF(); + const FloatV zero = V3Zero(); + const Vec3V cross01 = V3Cross(a.col0, a.col1); + const Vec3V cross12 = V3Cross(a.col1, a.col2); + const Vec3V cross20 = V3Cross(a.col2, a.col0); + const FloatV dot = V3Dot(cross01, a.col2); + const FloatV invDet = _mm_rcp_ps(dot); + const Vec3V mergeh = _mm_unpacklo_ps(cross12, cross01); + const Vec3V mergel = _mm_unpackhi_ps(cross12, cross01); + Vec3V colInv0 = _mm_unpacklo_ps(mergeh, cross20); + colInv0 = _mm_or_ps(_mm_andnot_ps(tttf, zero), _mm_and_ps(tttf, colInv0)); + const Vec3V zppd = _mm_shuffle_ps(mergeh, cross20, _MM_SHUFFLE(3, 0, 0, 2)); + const Vec3V pbwp = _mm_shuffle_ps(cross20, mergeh, _MM_SHUFFLE(3, 3, 1, 0)); + const Vec3V colInv1 = _mm_or_ps(_mm_andnot_ps(BTFFT(), pbwp), _mm_and_ps(BTFFT(), zppd)); + const Vec3V xppd = _mm_shuffle_ps(mergel, cross20, _MM_SHUFFLE(3, 0, 0, 0)); + const Vec3V pcyp = _mm_shuffle_ps(cross20, mergel, _MM_SHUFFLE(3, 1, 2, 0)); + const Vec3V colInv2 = _mm_or_ps(_mm_andnot_ps(tfft, pcyp), _mm_and_ps(tfft, xppd)); + + return Mat33V(_mm_mul_ps(colInv0, invDet), _mm_mul_ps(colInv1, invDet), _mm_mul_ps(colInv2, invDet)); +} + +PX_FORCE_INLINE Mat33V M33Trnsps(const Mat33V& a) +{ + Vec3V col0 = a.col0, col1 = a.col1, col2 = a.col2; + V3Transpose(col0, col1, col2); + return Mat33V(col0, col1, col2); +} + +PX_FORCE_INLINE Mat33V M33Identity() +{ + return Mat33V(V3UnitX(), V3UnitY(), V3UnitZ()); +} + +PX_FORCE_INLINE Mat33V M33Diagonal(const Vec3VArg d) +{ + const FloatV x = V3Mul(V3UnitX(), d); + const FloatV y = V3Mul(V3UnitY(), d); + const FloatV z = V3Mul(V3UnitZ(), d); + return Mat33V(x, y, z); +} + +////////////////////////////////// +// MAT34V +////////////////////////////////// + +PX_FORCE_INLINE Vec3V M34MulV3(const Mat34V& a, const Vec3V b) +{ + const FloatV x = V3GetX(b); + const FloatV y = V3GetY(b); + const FloatV z = V3GetZ(b); + const Vec3V v0 = V3Scale(a.col0, x); + const Vec3V v1 = V3Scale(a.col1, y); + const Vec3V v2 = V3Scale(a.col2, z); + const Vec3V v0PlusV1 = V3Add(v0, v1); + const Vec3V v0PlusV1Plusv2 = V3Add(v0PlusV1, v2); + return V3Add(v0PlusV1Plusv2, a.col3); +} + +PX_FORCE_INLINE Vec3V M34Mul33V3(const Mat34V& a, const Vec3V b) +{ + const FloatV x = V3GetX(b); + const FloatV y = V3GetY(b); + const FloatV z = V3GetZ(b); + const Vec3V v0 = V3Scale(a.col0, x); + const Vec3V v1 = V3Scale(a.col1, y); + const Vec3V v2 = V3Scale(a.col2, z); + const Vec3V v0PlusV1 = V3Add(v0, v1); + return V3Add(v0PlusV1, v2); +} + +PX_FORCE_INLINE Vec3V M34TrnspsMul33V3(const Mat34V& a, const Vec3V b) +{ + Vec3V v0 = V3Mul(a.col0, b); + Vec3V v1 = V3Mul(a.col1, b); + Vec3V v2 = V3Mul(a.col2, b); + V3Transpose(v0, v1, v2); + return V3Add(V3Add(v0, v1), v2); +} + +PX_FORCE_INLINE Mat34V M34MulM34(const Mat34V& a, const Mat34V& b) +{ + return Mat34V(M34Mul33V3(a, b.col0), M34Mul33V3(a, b.col1), M34Mul33V3(a, b.col2), M34MulV3(a, b.col3)); +} + +PX_FORCE_INLINE Mat33V M34MulM33(const Mat34V& a, const Mat33V& b) +{ + return Mat33V(M34Mul33V3(a, b.col0), M34Mul33V3(a, b.col1), M34Mul33V3(a, b.col2)); +} + +PX_FORCE_INLINE Mat33V M34Mul33MM34(const Mat34V& a, const Mat34V& b) +{ + return Mat33V(M34Mul33V3(a, b.col0), M34Mul33V3(a, b.col1), M34Mul33V3(a, b.col2)); +} + +PX_FORCE_INLINE Mat34V M34Add(const Mat34V& a, const Mat34V& b) +{ + return Mat34V(V3Add(a.col0, b.col0), V3Add(a.col1, b.col1), V3Add(a.col2, b.col2), V3Add(a.col3, b.col3)); +} + +PX_FORCE_INLINE Mat34V M34Inverse(const Mat34V& a) +{ + Mat34V aInv; + const BoolV tfft = BTFFT(); + const BoolV tttf = BTTTF(); + const FloatV zero = V3Zero(); + const Vec3V cross01 = V3Cross(a.col0, a.col1); + const Vec3V cross12 = V3Cross(a.col1, a.col2); + const Vec3V cross20 = V3Cross(a.col2, a.col0); + const FloatV dot = V3Dot(cross01, a.col2); + const FloatV invDet = _mm_rcp_ps(dot); + const Vec3V mergeh = _mm_unpacklo_ps(cross12, cross01); + const Vec3V mergel = _mm_unpackhi_ps(cross12, cross01); + Vec3V colInv0 = _mm_unpacklo_ps(mergeh, cross20); + colInv0 = _mm_or_ps(_mm_andnot_ps(tttf, zero), _mm_and_ps(tttf, colInv0)); + const Vec3V zppd = _mm_shuffle_ps(mergeh, cross20, _MM_SHUFFLE(3, 0, 0, 2)); + const Vec3V pbwp = _mm_shuffle_ps(cross20, mergeh, _MM_SHUFFLE(3, 3, 1, 0)); + const Vec3V colInv1 = _mm_or_ps(_mm_andnot_ps(BTFFT(), pbwp), _mm_and_ps(BTFFT(), zppd)); + const Vec3V xppd = _mm_shuffle_ps(mergel, cross20, _MM_SHUFFLE(3, 0, 0, 0)); + const Vec3V pcyp = _mm_shuffle_ps(cross20, mergel, _MM_SHUFFLE(3, 1, 2, 0)); + const Vec3V colInv2 = _mm_or_ps(_mm_andnot_ps(tfft, pcyp), _mm_and_ps(tfft, xppd)); + aInv.col0 = _mm_mul_ps(colInv0, invDet); + aInv.col1 = _mm_mul_ps(colInv1, invDet); + aInv.col2 = _mm_mul_ps(colInv2, invDet); + aInv.col3 = M34Mul33V3(aInv, V3Neg(a.col3)); + return aInv; +} + +PX_FORCE_INLINE Mat33V M34Trnsps33(const Mat34V& a) +{ + Vec3V col0 = a.col0, col1 = a.col1, col2 = a.col2; + V3Transpose(col0, col1, col2); + return Mat33V(col0, col1, col2); +} + +////////////////////////////////// +// MAT44V +////////////////////////////////// + +PX_FORCE_INLINE Vec4V M44MulV4(const Mat44V& a, const Vec4V b) +{ + const FloatV x = V4GetX(b); + const FloatV y = V4GetY(b); + const FloatV z = V4GetZ(b); + const FloatV w = V4GetW(b); + + const Vec4V v0 = V4Scale(a.col0, x); + const Vec4V v1 = V4Scale(a.col1, y); + const Vec4V v2 = V4Scale(a.col2, z); + const Vec4V v3 = V4Scale(a.col3, w); + const Vec4V v0PlusV1 = V4Add(v0, v1); + const Vec4V v0PlusV1Plusv2 = V4Add(v0PlusV1, v2); + return V4Add(v0PlusV1Plusv2, v3); +} + +PX_FORCE_INLINE Vec4V M44TrnspsMulV4(const Mat44V& a, const Vec4V b) +{ + Vec4V v0 = V4Mul(a.col0, b); + Vec4V v1 = V4Mul(a.col1, b); + Vec4V v2 = V4Mul(a.col2, b); + Vec4V v3 = V4Mul(a.col3, b); + V4Transpose(v0, v1, v2, v3); + return V4Add(V4Add(v0, v1), V4Add(v2, v3)); +} + +PX_FORCE_INLINE Mat44V M44MulM44(const Mat44V& a, const Mat44V& b) +{ + return Mat44V(M44MulV4(a, b.col0), M44MulV4(a, b.col1), M44MulV4(a, b.col2), M44MulV4(a, b.col3)); +} + +PX_FORCE_INLINE Mat44V M44Add(const Mat44V& a, const Mat44V& b) +{ + return Mat44V(V4Add(a.col0, b.col0), V4Add(a.col1, b.col1), V4Add(a.col2, b.col2), V4Add(a.col3, b.col3)); +} + +PX_FORCE_INLINE Mat44V M44Trnsps(const Mat44V& a) +{ + Vec4V col0 = a.col0, col1 = a.col1, col2 = a.col2, col3 = a.col3; + V4Transpose(col0, col1, col2, col3); + return Mat44V(col0, col1, col2, col3); +} + +PX_FORCE_INLINE Mat44V M44Inverse(const Mat44V& a) +{ + __m128 minor0, minor1, minor2, minor3; + __m128 row0, row1, row2, row3; + __m128 det, tmp1; + + tmp1 = V4Zero(); + row1 = V4Zero(); + row3 = V4Zero(); + + row0 = a.col0; + row1 = _mm_shuffle_ps(a.col1, a.col1, _MM_SHUFFLE(1, 0, 3, 2)); + row2 = a.col2; + row3 = _mm_shuffle_ps(a.col3, a.col3, _MM_SHUFFLE(1, 0, 3, 2)); + + tmp1 = _mm_mul_ps(row2, row3); + tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0xB1); + minor0 = _mm_mul_ps(row1, tmp1); + minor1 = _mm_mul_ps(row0, tmp1); + tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0x4E); + minor0 = _mm_sub_ps(_mm_mul_ps(row1, tmp1), minor0); + minor1 = _mm_sub_ps(_mm_mul_ps(row0, tmp1), minor1); + minor1 = _mm_shuffle_ps(minor1, minor1, 0x4E); + + tmp1 = _mm_mul_ps(row1, row2); + tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0xB1); + minor0 = _mm_add_ps(_mm_mul_ps(row3, tmp1), minor0); + minor3 = _mm_mul_ps(row0, tmp1); + tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0x4E); + minor0 = _mm_sub_ps(minor0, _mm_mul_ps(row3, tmp1)); + minor3 = _mm_sub_ps(_mm_mul_ps(row0, tmp1), minor3); + minor3 = _mm_shuffle_ps(minor3, minor3, 0x4E); + + tmp1 = _mm_mul_ps(_mm_shuffle_ps(row1, row1, 0x4E), row3); + tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0xB1); + row2 = _mm_shuffle_ps(row2, row2, 0x4E); + minor0 = _mm_add_ps(_mm_mul_ps(row2, tmp1), minor0); + minor2 = _mm_mul_ps(row0, tmp1); + tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0x4E); + minor0 = _mm_sub_ps(minor0, _mm_mul_ps(row2, tmp1)); + minor2 = _mm_sub_ps(_mm_mul_ps(row0, tmp1), minor2); + minor2 = _mm_shuffle_ps(minor2, minor2, 0x4E); + + tmp1 = _mm_mul_ps(row0, row1); + tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0xB1); + minor2 = _mm_add_ps(_mm_mul_ps(row3, tmp1), minor2); + minor3 = _mm_sub_ps(_mm_mul_ps(row2, tmp1), minor3); + tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0x4E); + minor2 = _mm_sub_ps(_mm_mul_ps(row3, tmp1), minor2); + minor3 = _mm_sub_ps(minor3, _mm_mul_ps(row2, tmp1)); + + tmp1 = _mm_mul_ps(row0, row3); + tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0xB1); + minor1 = _mm_sub_ps(minor1, _mm_mul_ps(row2, tmp1)); + minor2 = _mm_add_ps(_mm_mul_ps(row1, tmp1), minor2); + tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0x4E); + minor1 = _mm_add_ps(_mm_mul_ps(row2, tmp1), minor1); + minor2 = _mm_sub_ps(minor2, _mm_mul_ps(row1, tmp1)); + + tmp1 = _mm_mul_ps(row0, row2); + tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0xB1); + minor1 = _mm_add_ps(_mm_mul_ps(row3, tmp1), minor1); + minor3 = _mm_sub_ps(minor3, _mm_mul_ps(row1, tmp1)); + tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0x4E); + minor1 = _mm_sub_ps(minor1, _mm_mul_ps(row3, tmp1)); + minor3 = _mm_add_ps(_mm_mul_ps(row1, tmp1), minor3); + + det = _mm_mul_ps(row0, minor0); + det = _mm_add_ps(_mm_shuffle_ps(det, det, 0x4E), det); + det = _mm_add_ss(_mm_shuffle_ps(det, det, 0xB1), det); + tmp1 = _mm_rcp_ss(det); +#if 0 + det = _mm_sub_ss(_mm_add_ss(tmp1, tmp1), _mm_mul_ss(det, _mm_mul_ss(tmp1, tmp1))); + det = _mm_shuffle_ps(det, det, 0x00); +#else + det = _mm_shuffle_ps(tmp1, tmp1, _MM_SHUFFLE(0, 0, 0, 0)); +#endif + + minor0 = _mm_mul_ps(det, minor0); + minor1 = _mm_mul_ps(det, minor1); + minor2 = _mm_mul_ps(det, minor2); + minor3 = _mm_mul_ps(det, minor3); + Mat44V invTrans(minor0, minor1, minor2, minor3); + return M44Trnsps(invTrans); +} + +PX_FORCE_INLINE Vec4V V4LoadXYZW(const PxF32& x, const PxF32& y, const PxF32& z, const PxF32& w) +{ + return _mm_set_ps(w, z, y, x); +} + +PX_FORCE_INLINE VecU32V V4U32Sel(const BoolV c, const VecU32V a, const VecU32V b) +{ + return internalWindowsSimd::m128_I2F( + _mm_or_si128(_mm_andnot_si128(internalWindowsSimd::m128_F2I(c), internalWindowsSimd::m128_F2I(b)), + _mm_and_si128(internalWindowsSimd::m128_F2I(c), internalWindowsSimd::m128_F2I(a)))); +} + +PX_FORCE_INLINE VecU32V V4U32or(VecU32V a, VecU32V b) +{ + return internalWindowsSimd::m128_I2F(_mm_or_si128(internalWindowsSimd::m128_F2I(a), internalWindowsSimd::m128_F2I(b))); +} + +PX_FORCE_INLINE VecU32V V4U32xor(VecU32V a, VecU32V b) +{ + return internalWindowsSimd::m128_I2F( + _mm_xor_si128(internalWindowsSimd::m128_F2I(a), internalWindowsSimd::m128_F2I(b))); +} + +PX_FORCE_INLINE VecU32V V4U32and(VecU32V a, VecU32V b) +{ + return internalWindowsSimd::m128_I2F( + _mm_and_si128(internalWindowsSimd::m128_F2I(a), internalWindowsSimd::m128_F2I(b))); +} + +PX_FORCE_INLINE VecU32V V4U32Andc(VecU32V a, VecU32V b) +{ + return internalWindowsSimd::m128_I2F( + _mm_andnot_si128(internalWindowsSimd::m128_F2I(b), internalWindowsSimd::m128_F2I(a))); +} + +PX_FORCE_INLINE VecI32V U4Load(const PxU32 i) +{ + return _mm_load1_ps((PxF32*)&i); +} + +PX_FORCE_INLINE VecU32V U4LoadU(const PxU32* i) +{ + return _mm_loadu_ps((PxF32*)i); +} + +PX_FORCE_INLINE VecU32V U4LoadA(const PxU32* i) +{ + ASSERT_ISALIGNED16(i); + return _mm_load_ps((PxF32*)i); +} + +PX_FORCE_INLINE VecI32V I4Load(const PxI32 i) +{ + return _mm_load1_ps((PxF32*)&i); +} + +PX_FORCE_INLINE VecI32V I4LoadU(const PxI32* i) +{ + return _mm_loadu_ps((PxF32*)i); +} + +PX_FORCE_INLINE VecI32V I4LoadA(const PxI32* i) +{ + ASSERT_ISALIGNED16(i); + return _mm_load_ps((PxF32*)i); +} + +PX_FORCE_INLINE VecI32V VecI32V_Add(const VecI32VArg a, const VecI32VArg b) +{ + return internalWindowsSimd::m128_I2F( + _mm_add_epi32(internalWindowsSimd::m128_F2I(a), internalWindowsSimd::m128_F2I(b))); +} + +PX_FORCE_INLINE VecI32V VecI32V_Sub(const VecI32VArg a, const VecI32VArg b) +{ + return internalWindowsSimd::m128_I2F( + _mm_sub_epi32(internalWindowsSimd::m128_F2I(a), internalWindowsSimd::m128_F2I(b))); +} + +PX_FORCE_INLINE BoolV VecI32V_IsGrtr(const VecI32VArg a, const VecI32VArg b) +{ + return internalWindowsSimd::m128_I2F( + _mm_cmpgt_epi32(internalWindowsSimd::m128_F2I(a), internalWindowsSimd::m128_F2I(b))); +} + +PX_FORCE_INLINE BoolV VecI32V_IsEq(const VecI32VArg a, const VecI32VArg b) +{ + return internalWindowsSimd::m128_I2F( + _mm_cmpeq_epi32(internalWindowsSimd::m128_F2I(a), internalWindowsSimd::m128_F2I(b))); +} + +PX_FORCE_INLINE VecI32V V4I32Sel(const BoolV c, const VecI32V a, const VecI32V b) +{ + return V4U32Sel(c, a, b); +} + +PX_FORCE_INLINE VecI32V VecI32V_Zero() +{ + return V4Zero(); +} + +PX_FORCE_INLINE VecI32V VecI32V_One() +{ + return I4Load(1); +} + +PX_FORCE_INLINE VecI32V VecI32V_Two() +{ + return I4Load(2); +} + +PX_FORCE_INLINE VecI32V VecI32V_MinusOne() +{ + return I4Load(-1); +} + +PX_FORCE_INLINE VecU32V U4Zero() +{ + return U4Load(0); +} + +PX_FORCE_INLINE VecU32V U4One() +{ + return U4Load(1); +} + +PX_FORCE_INLINE VecU32V U4Two() +{ + return U4Load(2); +} + +PX_FORCE_INLINE VecI32V VecI32V_Sel(const BoolV c, const VecI32VArg a, const VecI32VArg b) +{ + PX_ASSERT(_VecMathTests::allElementsEqualBoolV(c, BTTTT()) || + _VecMathTests::allElementsEqualBoolV(c, BFFFF())); + return _mm_or_ps(_mm_andnot_ps(c, b), _mm_and_ps(c, a)); +} + +PX_FORCE_INLINE VecShiftV VecI32V_PrepareShift(const VecI32VArg shift) +{ + VecShiftV preparedShift; + preparedShift.shift = _mm_or_ps(_mm_andnot_ps(BTFFF(), VecI32V_Zero()), _mm_and_ps(BTFFF(), shift)); + return preparedShift; +} + +PX_FORCE_INLINE VecI32V VecI32V_LeftShift(const VecI32VArg a, const VecShiftVArg count) +{ + return internalWindowsSimd::m128_I2F( + _mm_sll_epi32(internalWindowsSimd::m128_F2I(a), internalWindowsSimd::m128_F2I(count.shift))); +} + +PX_FORCE_INLINE VecI32V VecI32V_RightShift(const VecI32VArg a, const VecShiftVArg count) +{ + return internalWindowsSimd::m128_I2F( + _mm_srl_epi32(internalWindowsSimd::m128_F2I(a), internalWindowsSimd::m128_F2I(count.shift))); +} + +PX_FORCE_INLINE VecI32V VecI32V_And(const VecI32VArg a, const VecI32VArg b) +{ + return _mm_and_ps(a, b); +} + +PX_FORCE_INLINE VecI32V VecI32V_Or(const VecI32VArg a, const VecI32VArg b) +{ + return _mm_or_ps(a, b); +} + +PX_FORCE_INLINE VecI32V VecI32V_GetX(const VecI32VArg a) +{ + return _mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0)); +} + +PX_FORCE_INLINE VecI32V VecI32V_GetY(const VecI32VArg a) +{ + return _mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 1, 1, 1)); +} + +PX_FORCE_INLINE VecI32V VecI32V_GetZ(const VecI32VArg a) +{ + return _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2)); +} + +PX_FORCE_INLINE VecI32V VecI32V_GetW(const VecI32VArg a) +{ + return _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 3, 3, 3)); +} + +PX_FORCE_INLINE void PxI32_From_VecI32V(const VecI32VArg a, PxI32* i) +{ + _mm_store_ss((PxF32*)i, a); +} + +PX_FORCE_INLINE VecI32V VecI32V_From_BoolV(const BoolVArg a) +{ + return a; +} + +PX_FORCE_INLINE VecU32V VecU32V_From_BoolV(const BoolVArg a) +{ + return a; +} + +PX_FORCE_INLINE VecI32V VecI32V_Merge(const VecI32VArg a, const VecI32VArg b, const VecI32VArg c, const VecI32VArg d) +{ + const __m128 xw = _mm_move_ss(b, a); // y, y, y, x + const __m128 yz = _mm_move_ss(c, d); // z, z, z, w + return _mm_shuffle_ps(xw, yz, _MM_SHUFFLE(0, 2, 1, 0)); +} + +PX_FORCE_INLINE void V4U32StoreAligned(VecU32V val, VecU32V* address) +{ + *address = val; +} + +PX_FORCE_INLINE Vec4V V4Andc(const Vec4V a, const VecU32V b) +{ + VecU32V result32(a); + result32 = V4U32Andc(result32, b); + return Vec4V(result32); +} + +PX_FORCE_INLINE VecU32V V4IsGrtrV32u(const Vec4V a, const Vec4V b) +{ + return V4IsGrtr(a, b); +} + +PX_FORCE_INLINE VecU16V V4U16LoadAligned(VecU16V* addr) +{ + return *addr; +} + +PX_FORCE_INLINE VecU16V V4U16LoadUnaligned(VecU16V* addr) +{ + return *addr; +} + +// unsigned compares are not supported on x86 +PX_FORCE_INLINE VecU16V V4U16CompareGt(VecU16V a, VecU16V b) +{ + // _mm_cmpgt_epi16 doesn't work for unsigned values unfortunately + // return m128_I2F(_mm_cmpgt_epi16(internalWindowsSimd::m128_F2I(a), internalWindowsSimd::m128_F2I(b))); + VecU16V result; + result.m128_u16[0] = PxU16((a).m128_u16[0] > (b).m128_u16[0]); + result.m128_u16[1] = PxU16((a).m128_u16[1] > (b).m128_u16[1]); + result.m128_u16[2] = PxU16((a).m128_u16[2] > (b).m128_u16[2]); + result.m128_u16[3] = PxU16((a).m128_u16[3] > (b).m128_u16[3]); + result.m128_u16[4] = PxU16((a).m128_u16[4] > (b).m128_u16[4]); + result.m128_u16[5] = PxU16((a).m128_u16[5] > (b).m128_u16[5]); + result.m128_u16[6] = PxU16((a).m128_u16[6] > (b).m128_u16[6]); + result.m128_u16[7] = PxU16((a).m128_u16[7] > (b).m128_u16[7]); + return result; +} + +PX_FORCE_INLINE VecU16V V4I16CompareGt(VecU16V a, VecU16V b) +{ + return internalWindowsSimd::m128_I2F( + _mm_cmpgt_epi16(internalWindowsSimd::m128_F2I(a), internalWindowsSimd::m128_F2I(b))); +} + +PX_FORCE_INLINE Vec4V Vec4V_From_VecU32V(VecU32V a) +{ + Vec4V result = V4LoadXYZW(PxF32(a.m128_u32[0]), PxF32(a.m128_u32[1]), PxF32(a.m128_u32[2]), PxF32(a.m128_u32[3])); + return result; +} + +PX_FORCE_INLINE Vec4V Vec4V_From_VecI32V(VecI32V a) +{ + return _mm_cvtepi32_ps(internalWindowsSimd::m128_F2I(a)); +} + +PX_FORCE_INLINE VecI32V VecI32V_From_Vec4V(Vec4V a) +{ + return internalWindowsSimd::m128_I2F(_mm_cvttps_epi32(a)); +} + +PX_FORCE_INLINE Vec4V Vec4V_ReinterpretFrom_VecU32V(VecU32V a) +{ + return Vec4V(a); +} + +PX_FORCE_INLINE Vec4V Vec4V_ReinterpretFrom_VecI32V(VecI32V a) +{ + return Vec4V(a); +} + +PX_FORCE_INLINE VecU32V VecU32V_ReinterpretFrom_Vec4V(Vec4V a) +{ + return VecU32V(a); +} + +PX_FORCE_INLINE VecI32V VecI32V_ReinterpretFrom_Vec4V(Vec4V a) +{ + return VecI32V(a); +} + +template +PX_FORCE_INLINE VecU32V V4U32SplatElement(VecU32V a) +{ + return internalWindowsSimd::m128_I2F( + _mm_shuffle_epi32(internalWindowsSimd::m128_F2I(a), _MM_SHUFFLE(index, index, index, index))); +} + +template +PX_FORCE_INLINE Vec4V V4SplatElement(Vec4V a) +{ + return internalWindowsSimd::m128_I2F( + _mm_shuffle_epi32(internalWindowsSimd::m128_F2I(a), _MM_SHUFFLE(index, index, index, index))); +} + +PX_FORCE_INLINE VecU32V U4LoadXYZW(PxU32 x, PxU32 y, PxU32 z, PxU32 w) +{ + VecU32V result; + result.m128_u32[0] = x; + result.m128_u32[1] = y; + result.m128_u32[2] = z; + result.m128_u32[3] = w; + return result; +} + +PX_FORCE_INLINE Vec4V V4ConvertFromI32V(const VecI32V in) +{ + return _mm_cvtepi32_ps(internalWindowsSimd::m128_F2I(in)); +} + +} // namespace aos +} // namespace shdfnd +} // namespace physx + +#endif // PSFOUNDATION_PSWINDOWSINLINEAOS_H diff --git a/sources/PhysX/PhysX/source/foundation/include/windows/PsWindowsIntrinsics.h b/sources/PhysX/PhysX/source/foundation/include/windows/PsWindowsIntrinsics.h new file mode 100644 index 00000000..9ae435d7 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/windows/PsWindowsIntrinsics.h @@ -0,0 +1,193 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSWINDOWSINTRINSICS_H +#define PSFOUNDATION_PSWINDOWSINTRINSICS_H + +#include "Ps.h" +#include "foundation/PxAssert.h" + +// this file is for internal intrinsics - that is, intrinsics that are used in +// cross platform code but do not appear in the API + +#if !PX_WINDOWS_FAMILY +#error "This file should only be included by Windows builds!!" +#endif + +#pragma warning(push) +//'symbol' is not defined as a preprocessor macro, replacing with '0' for 'directives' +#pragma warning(disable : 4668) +#if PX_VC == 10 +#pragma warning(disable : 4987) // nonstandard extension used: 'throw (...)' +#endif +#include +#pragma warning(pop) + +#pragma warning(push) +#pragma warning(disable : 4985) // 'symbol name': attributes not present on previous declaration +#include +#pragma warning(pop) + +#include +// do not include for ARM target +#if !PX_ARM && !PX_A64 +#include +#endif + +#pragma intrinsic(_BitScanForward) +#pragma intrinsic(_BitScanReverse) + +namespace physx +{ +namespace shdfnd +{ + +/* +* Implements a memory barrier +*/ +PX_FORCE_INLINE void memoryBarrier() +{ + _ReadWriteBarrier(); + /* long Barrier; + __asm { + xchg Barrier, eax + }*/ +} + +/*! +Returns the index of the highest set bit. Not valid for zero arg. +*/ +PX_FORCE_INLINE uint32_t highestSetBitUnsafe(uint32_t v) +{ + unsigned long retval; + _BitScanReverse(&retval, v); + return retval; +} + +/*! +Returns the index of the highest set bit. Undefined for zero arg. +*/ +PX_FORCE_INLINE uint32_t lowestSetBitUnsafe(uint32_t v) +{ + unsigned long retval; + _BitScanForward(&retval, v); + return retval; +} + +/*! +Returns the number of leading zeros in v. Returns 32 for v=0. +*/ +PX_FORCE_INLINE uint32_t countLeadingZeros(uint32_t v) +{ + if(v) + { + unsigned long bsr = (unsigned long)-1; + _BitScanReverse(&bsr, v); + return 31 - bsr; + } + else + return 32; +} + +/*! +Prefetch aligned cache size around \c ptr+offset. +*/ +#if !PX_ARM && !PX_A64 +PX_FORCE_INLINE void prefetchLine(const void* ptr, uint32_t offset = 0) +{ + // cache line on X86/X64 is 64-bytes so a 128-byte prefetch would require 2 prefetches. + // However, we can only dispatch a limited number of prefetch instructions so we opt to prefetch just 1 cache line + /*_mm_prefetch(((const char*)ptr + offset), _MM_HINT_T0);*/ + // We get slightly better performance prefetching to non-temporal addresses instead of all cache levels + _mm_prefetch(((const char*)ptr + offset), _MM_HINT_NTA); +} +#else +PX_FORCE_INLINE void prefetchLine(const void* ptr, uint32_t offset = 0) +{ + // arm does have 32b cache line size + __prefetch(((const char*)ptr + offset)); +} +#endif + +/*! +Prefetch \c count bytes starting at \c ptr. +*/ +#if !PX_ARM +PX_FORCE_INLINE void prefetch(const void* ptr, uint32_t count = 1) +{ + const char* cp = (char*)ptr; + uint64_t p = size_t(ptr); + uint64_t startLine = p >> 6, endLine = (p + count - 1) >> 6; + uint64_t lines = endLine - startLine + 1; + do + { + prefetchLine(cp); + cp += 64; + } while(--lines); +} +#else +PX_FORCE_INLINE void prefetch(const void* ptr, uint32_t count = 1) +{ + const char* cp = (char*)ptr; + uint32_t p = size_t(ptr); + uint32_t startLine = p >> 5, endLine = (p + count - 1) >> 5; + uint32_t lines = endLine - startLine + 1; + do + { + prefetchLine(cp); + cp += 32; + } while(--lines); +} +#endif + +//! \brief platform-specific reciprocal +PX_CUDA_CALLABLE PX_FORCE_INLINE float recipFast(float a) +{ + return 1.0f / a; +} + +//! \brief platform-specific fast reciprocal square root +PX_CUDA_CALLABLE PX_FORCE_INLINE float recipSqrtFast(float a) +{ + return 1.0f / ::sqrtf(a); +} + +//! \brief platform-specific floor +PX_CUDA_CALLABLE PX_FORCE_INLINE float floatFloor(float x) +{ + return ::floorf(x); +} + +#define NS_EXPECT_TRUE(x) x +#define NS_EXPECT_FALSE(x) x + +} // namespace shdfnd +} // namespace physx + +#endif // #ifndef PSFOUNDATION_PSWINDOWSINTRINSICS_H diff --git a/sources/PhysX/PhysX/source/foundation/include/windows/PsWindowsTrigConstants.h b/sources/PhysX/PhysX/source/foundation/include/windows/PsWindowsTrigConstants.h new file mode 100644 index 00000000..4eec94e8 --- /dev/null +++ b/sources/PhysX/PhysX/source/foundation/include/windows/PsWindowsTrigConstants.h @@ -0,0 +1,98 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSWINDOWSTRIGCONSTANTS_H +#define PSFOUNDATION_PSWINDOWSTRIGCONSTANTS_H + +namespace physx +{ +namespace shdfnd +{ +namespace aos +{ + +#define PX_GLOBALCONST extern const __declspec(selectany) + +__declspec(align(16)) struct PX_VECTORF32 +{ + float f[4]; +}; + +//#define PX_PI 3.141592654f +//#define PX_2PI 6.283185307f +//#define PX_1DIVPI 0.318309886f +//#define PX_1DIV2PI 0.159154943f +//#define PX_PIDIV2 1.570796327f +//#define PX_PIDIV4 0.785398163f + +PX_GLOBALCONST PX_VECTORF32 g_PXSinCoefficients0 = { { 1.0f, -0.166666667f, 8.333333333e-3f, -1.984126984e-4f } }; +PX_GLOBALCONST PX_VECTORF32 +g_PXSinCoefficients1 = { { 2.755731922e-6f, -2.505210839e-8f, 1.605904384e-10f, -7.647163732e-13f } }; +PX_GLOBALCONST PX_VECTORF32 +g_PXSinCoefficients2 = { { 2.811457254e-15f, -8.220635247e-18f, 1.957294106e-20f, -3.868170171e-23f } }; +PX_GLOBALCONST PX_VECTORF32 g_PXCosCoefficients0 = { { 1.0f, -0.5f, 4.166666667e-2f, -1.388888889e-3f } }; +PX_GLOBALCONST PX_VECTORF32 +g_PXCosCoefficients1 = { { 2.480158730e-5f, -2.755731922e-7f, 2.087675699e-9f, -1.147074560e-11f } }; +PX_GLOBALCONST PX_VECTORF32 +g_PXCosCoefficients2 = { { 4.779477332e-14f, -1.561920697e-16f, 4.110317623e-19f, -8.896791392e-22f } }; +PX_GLOBALCONST PX_VECTORF32 g_PXTanCoefficients0 = { { 1.0f, 0.333333333f, 0.133333333f, 5.396825397e-2f } }; +PX_GLOBALCONST PX_VECTORF32 +g_PXTanCoefficients1 = { { 2.186948854e-2f, 8.863235530e-3f, 3.592128167e-3f, 1.455834485e-3f } }; +PX_GLOBALCONST PX_VECTORF32 +g_PXTanCoefficients2 = { { 5.900274264e-4f, 2.391290764e-4f, 9.691537707e-5f, 3.927832950e-5f } }; +PX_GLOBALCONST PX_VECTORF32 +g_PXASinCoefficients0 = { { -0.05806367563904f, -0.41861972469416f, 0.22480114791621f, 2.17337241360606f } }; +PX_GLOBALCONST PX_VECTORF32 +g_PXASinCoefficients1 = { { 0.61657275907170f, 4.29696498283455f, -1.18942822255452f, -6.53784832094831f } }; +PX_GLOBALCONST PX_VECTORF32 +g_PXASinCoefficients2 = { { -1.36926553863413f, -4.48179294237210f, 1.41810672941833f, 5.48179257935713f } }; +PX_GLOBALCONST PX_VECTORF32 g_PXATanCoefficients0 = { { 1.0f, 0.333333334f, 0.2f, 0.142857143f } }; +PX_GLOBALCONST PX_VECTORF32 +g_PXATanCoefficients1 = { { 1.111111111e-1f, 9.090909091e-2f, 7.692307692e-2f, 6.666666667e-2f } }; +PX_GLOBALCONST PX_VECTORF32 +g_PXATanCoefficients2 = { { 5.882352941e-2f, 5.263157895e-2f, 4.761904762e-2f, 4.347826087e-2f } }; +PX_GLOBALCONST PX_VECTORF32 +g_PXSinEstCoefficients = { { 1.0f, -1.66521856991541e-1f, 8.199913018755e-3f, -1.61475937228e-4f } }; +PX_GLOBALCONST PX_VECTORF32 +g_PXCosEstCoefficients = { { 1.0f, -4.95348008918096e-1f, 3.878259962881e-2f, -9.24587976263e-4f } }; +PX_GLOBALCONST PX_VECTORF32 g_PXTanEstCoefficients = { { 2.484f, -1.954923183e-1f, 2.467401101f, PxInvPi } }; +PX_GLOBALCONST PX_VECTORF32 +g_PXATanEstCoefficients = { { 7.689891418951e-1f, 1.104742493348f, 8.661844266006e-1f, PxPiDivTwo } }; +PX_GLOBALCONST PX_VECTORF32 +g_PXASinEstCoefficients = { { -1.36178272886711f, 2.37949493464538f, -8.08228565650486e-1f, 2.78440142746736e-1f } }; +PX_GLOBALCONST PX_VECTORF32 g_PXASinEstConstants = { { 1.00000011921f, PxPiDivTwo, 0.0f, 0.0f } }; +PX_GLOBALCONST PX_VECTORF32 g_PXPiConstants0 = { { PxPi, PxTwoPi, PxInvPi, PxInvTwoPi } }; +PX_GLOBALCONST PX_VECTORF32 g_PXReciprocalTwoPi = { { PxInvTwoPi, PxInvTwoPi, PxInvTwoPi, PxInvTwoPi } }; +PX_GLOBALCONST PX_VECTORF32 g_PXTwoPi = { { PxTwoPi, PxTwoPi, PxTwoPi, PxTwoPi } }; + +} // namespace aos +} // namespace shdfnd +} // namespace physx + +#endif diff --git a/sources/PhysX/PxShared/include/foundation/Px.h b/sources/PhysX/PxShared/include/foundation/Px.h new file mode 100644 index 00000000..e4e53415 --- /dev/null +++ b/sources/PhysX/PxShared/include/foundation/Px.h @@ -0,0 +1,92 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PXFOUNDATION_PX_H +#define PXFOUNDATION_PX_H + +/** \addtogroup foundation +@{ +*/ + +#include "foundation/PxSimpleTypes.h" + +/** files to always include */ +#include +#include + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +typedef uint32_t PxU32; + +class PxAllocatorCallback; +class PxErrorCallback; +struct PxErrorCode; +class PxAssertHandler; + +class PxInputStream; +class PxInputData; +class PxOutputStream; + +class PxVec2; +class PxVec3; +class PxVec4; +class PxMat33; +class PxMat44; +class PxPlane; +class PxQuat; +class PxTransform; +class PxBounds3; + +/** enum for empty constructor tag*/ +enum PxEMPTY +{ + PxEmpty +}; + +/** enum for zero constructor tag for vectors and matrices */ +enum PxZERO +{ + PxZero +}; + +/** enum for identity constructor flag for quaternions, transforms, and matrices */ +enum PxIDENTITY +{ + PxIdentity +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif // #ifndef PXFOUNDATION_PX_H diff --git a/sources/PhysX/PxShared/include/foundation/PxAllocatorCallback.h b/sources/PhysX/PxShared/include/foundation/PxAllocatorCallback.h new file mode 100644 index 00000000..4e9487d8 --- /dev/null +++ b/sources/PhysX/PxShared/include/foundation/PxAllocatorCallback.h @@ -0,0 +1,95 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PXFOUNDATION_PXALLOCATORCALLBACK_H +#define PXFOUNDATION_PXALLOCATORCALLBACK_H + +/** \addtogroup foundation +@{ +*/ + +#include "foundation/Px.h" +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief Abstract base class for an application defined memory allocator that can be used by the Nv library. + +\note The SDK state should not be modified from within any allocation/free function. + +Threading: All methods of this class should be thread safe as it can be called from the user thread +or the physics processing thread(s). +*/ + +class PxAllocatorCallback +{ + public: + /** + \brief destructor + */ + virtual ~PxAllocatorCallback() + { + } + + /** + \brief Allocates size bytes of memory, which must be 16-byte aligned. + + This method should never return NULL. If you run out of memory, then + you should terminate the app or take some other appropriate action. + + Threading: This function should be thread safe as it can be called in the context of the user thread + and physics processing thread(s). + + \param size Number of bytes to allocate. + \param typeName Name of the datatype that is being allocated + \param filename The source file which allocated the memory + \param line The source line which allocated the memory + \return The allocated block of memory. + */ + virtual void* allocate(size_t size, const char* typeName, const char* filename, int line) = 0; + + /** + \brief Frees memory previously allocated by allocate(). + + Threading: This function should be thread safe as it can be called in the context of the user thread + and physics processing thread(s). + + \param ptr Memory to free. + */ + virtual void deallocate(void* ptr) = 0; +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif // #ifndef PXFOUNDATION_PXALLOCATORCALLBACK_H diff --git a/sources/PhysX/PxShared/include/foundation/PxBitAndData.h b/sources/PhysX/PxShared/include/foundation/PxBitAndData.h new file mode 100644 index 00000000..e5692997 --- /dev/null +++ b/sources/PhysX/PxShared/include/foundation/PxBitAndData.h @@ -0,0 +1,87 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PXFOUNDATION_PXBITANDDATA_H +#define PXFOUNDATION_PXBITANDDATA_H + +#include "foundation/Px.h" + +/** \addtogroup foundation + @{ +*/ +#if !PX_DOXYGEN +namespace physx +{ +#endif + +template +class PxBitAndDataT +{ + public: + PX_FORCE_INLINE PxBitAndDataT(const PxEMPTY) + { + } + PX_FORCE_INLINE PxBitAndDataT() : mData(0) + { + } + PX_FORCE_INLINE PxBitAndDataT(storageType data, bool bit = false) + { + mData = bit ? storageType(data | bitMask) : data; + } + + PX_CUDA_CALLABLE PX_FORCE_INLINE operator storageType() const + { + return storageType(mData & ~bitMask); + } + PX_CUDA_CALLABLE PX_FORCE_INLINE void setBit() + { + mData |= bitMask; + } + PX_CUDA_CALLABLE PX_FORCE_INLINE void clearBit() + { + mData &= ~bitMask; + } + PX_CUDA_CALLABLE PX_FORCE_INLINE storageType isBitSet() const + { + return storageType(mData & bitMask); + } + + protected: + storageType mData; +}; +typedef PxBitAndDataT PxBitAndByte; +typedef PxBitAndDataT PxBitAndWord; +typedef PxBitAndDataT PxBitAndDword; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif // PXFOUNDATION_PXBITANDDATA_H diff --git a/sources/PhysX/PxShared/include/foundation/PxBounds3.h b/sources/PhysX/PxShared/include/foundation/PxBounds3.h new file mode 100644 index 00000000..ef8ead25 --- /dev/null +++ b/sources/PhysX/PxShared/include/foundation/PxBounds3.h @@ -0,0 +1,480 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PXFOUNDATION_PXBOUNDS3_H +#define PXFOUNDATION_PXBOUNDS3_H + +/** \addtogroup foundation +@{ +*/ + +#include "foundation/PxTransform.h" +#include "foundation/PxMat33.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +// maximum extents defined such that floating point exceptions are avoided for standard use cases +#define PX_MAX_BOUNDS_EXTENTS (PX_MAX_REAL * 0.25f) + +/** +\brief Class representing 3D range or axis aligned bounding box. + +Stored as minimum and maximum extent corners. Alternate representation +would be center and dimensions. +May be empty or nonempty. For nonempty bounds, minimum <= maximum has to hold for all axes. +Empty bounds have to be represented as minimum = PX_MAX_BOUNDS_EXTENTS and maximum = -PX_MAX_BOUNDS_EXTENTS for all +axes. +All other representations are invalid and the behavior is undefined. +*/ +class PxBounds3 +{ + public: + /** + \brief Default constructor, not performing any initialization for performance reason. + \remark Use empty() function below to construct empty bounds. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxBounds3() + { + } + + /** + \brief Construct from two bounding points + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxBounds3(const PxVec3& minimum, const PxVec3& maximum); + + /** + \brief Return empty bounds. + */ + static PX_CUDA_CALLABLE PX_FORCE_INLINE PxBounds3 empty(); + + /** + \brief returns the AABB containing v0 and v1. + \param v0 first point included in the AABB. + \param v1 second point included in the AABB. + */ + static PX_CUDA_CALLABLE PX_FORCE_INLINE PxBounds3 boundsOfPoints(const PxVec3& v0, const PxVec3& v1); + + /** + \brief returns the AABB from center and extents vectors. + \param center Center vector + \param extent Extents vector + */ + static PX_CUDA_CALLABLE PX_FORCE_INLINE PxBounds3 centerExtents(const PxVec3& center, const PxVec3& extent); + + /** + \brief Construct from center, extent, and (not necessarily orthogonal) basis + */ + static PX_CUDA_CALLABLE PX_INLINE PxBounds3 + basisExtent(const PxVec3& center, const PxMat33& basis, const PxVec3& extent); + + /** + \brief Construct from pose and extent + */ + static PX_CUDA_CALLABLE PX_INLINE PxBounds3 poseExtent(const PxTransform& pose, const PxVec3& extent); + + /** + \brief gets the transformed bounds of the passed AABB (resulting in a bigger AABB). + + This version is safe to call for empty bounds. + + \param[in] matrix Transform to apply, can contain scaling as well + \param[in] bounds The bounds to transform. + */ + static PX_CUDA_CALLABLE PX_INLINE PxBounds3 transformSafe(const PxMat33& matrix, const PxBounds3& bounds); + + /** + \brief gets the transformed bounds of the passed AABB (resulting in a bigger AABB). + + Calling this method for empty bounds leads to undefined behavior. Use #transformSafe() instead. + + \param[in] matrix Transform to apply, can contain scaling as well + \param[in] bounds The bounds to transform. + */ + static PX_CUDA_CALLABLE PX_INLINE PxBounds3 transformFast(const PxMat33& matrix, const PxBounds3& bounds); + + /** + \brief gets the transformed bounds of the passed AABB (resulting in a bigger AABB). + + This version is safe to call for empty bounds. + + \param[in] transform Transform to apply, can contain scaling as well + \param[in] bounds The bounds to transform. + */ + static PX_CUDA_CALLABLE PX_INLINE PxBounds3 transformSafe(const PxTransform& transform, const PxBounds3& bounds); + + /** + \brief gets the transformed bounds of the passed AABB (resulting in a bigger AABB). + + Calling this method for empty bounds leads to undefined behavior. Use #transformSafe() instead. + + \param[in] transform Transform to apply, can contain scaling as well + \param[in] bounds The bounds to transform. + */ + static PX_CUDA_CALLABLE PX_INLINE PxBounds3 transformFast(const PxTransform& transform, const PxBounds3& bounds); + + /** + \brief Sets empty to true + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE void setEmpty(); + + /** + \brief Sets the bounds to maximum size [-PX_MAX_BOUNDS_EXTENTS, PX_MAX_BOUNDS_EXTENTS]. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE void setMaximal(); + + /** + \brief expands the volume to include v + \param v Point to expand to. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE void include(const PxVec3& v); + + /** + \brief expands the volume to include b. + \param b Bounds to perform union with. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE void include(const PxBounds3& b); + + PX_CUDA_CALLABLE PX_FORCE_INLINE bool isEmpty() const; + + /** + \brief indicates whether the intersection of this and b is empty or not. + \param b Bounds to test for intersection. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE bool intersects(const PxBounds3& b) const; + + /** + \brief computes the 1D-intersection between two AABBs, on a given axis. + \param a the other AABB + \param axis the axis (0, 1, 2) + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE bool intersects1D(const PxBounds3& a, uint32_t axis) const; + + /** + \brief indicates if these bounds contain v. + \param v Point to test against bounds. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE bool contains(const PxVec3& v) const; + + /** + \brief checks a box is inside another box. + \param box the other AABB + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE bool isInside(const PxBounds3& box) const; + + /** + \brief returns the center of this axis aligned box. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 getCenter() const; + + /** + \brief get component of the box's center along a given axis + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE float getCenter(uint32_t axis) const; + + /** + \brief get component of the box's extents along a given axis + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE float getExtents(uint32_t axis) const; + + /** + \brief returns the dimensions (width/height/depth) of this axis aligned box. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 getDimensions() const; + + /** + \brief returns the extents, which are half of the width/height/depth. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 getExtents() const; + + /** + \brief scales the AABB. + + This version is safe to call for empty bounds. + + \param scale Factor to scale AABB by. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE void scaleSafe(float scale); + + /** + \brief scales the AABB. + + Calling this method for empty bounds leads to undefined behavior. Use #scaleSafe() instead. + + \param scale Factor to scale AABB by. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE void scaleFast(float scale); + + /** + fattens the AABB in all 3 dimensions by the given distance. + + This version is safe to call for empty bounds. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE void fattenSafe(float distance); + + /** + fattens the AABB in all 3 dimensions by the given distance. + + Calling this method for empty bounds leads to undefined behavior. Use #fattenSafe() instead. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE void fattenFast(float distance); + + /** + checks that the AABB values are not NaN + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE bool isFinite() const; + + /** + checks that the AABB values describe a valid configuration. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE bool isValid() const; + + PxVec3 minimum, maximum; +}; + +PX_CUDA_CALLABLE PX_FORCE_INLINE PxBounds3::PxBounds3(const PxVec3& minimum_, const PxVec3& maximum_) +: minimum(minimum_), maximum(maximum_) +{ +} + +PX_CUDA_CALLABLE PX_FORCE_INLINE PxBounds3 PxBounds3::empty() +{ + return PxBounds3(PxVec3(PX_MAX_BOUNDS_EXTENTS), PxVec3(-PX_MAX_BOUNDS_EXTENTS)); +} + +PX_CUDA_CALLABLE PX_FORCE_INLINE bool PxBounds3::isFinite() const +{ + return minimum.isFinite() && maximum.isFinite(); +} + +PX_CUDA_CALLABLE PX_FORCE_INLINE PxBounds3 PxBounds3::boundsOfPoints(const PxVec3& v0, const PxVec3& v1) +{ + return PxBounds3(v0.minimum(v1), v0.maximum(v1)); +} + +PX_CUDA_CALLABLE PX_FORCE_INLINE PxBounds3 PxBounds3::centerExtents(const PxVec3& center, const PxVec3& extent) +{ + return PxBounds3(center - extent, center + extent); +} + +PX_CUDA_CALLABLE PX_INLINE PxBounds3 +PxBounds3::basisExtent(const PxVec3& center, const PxMat33& basis, const PxVec3& extent) +{ + // extended basis vectors + PxVec3 c0 = basis.column0 * extent.x; + PxVec3 c1 = basis.column1 * extent.y; + PxVec3 c2 = basis.column2 * extent.z; + + PxVec3 w; + // find combination of base vectors that produces max. distance for each component = sum of abs() + w.x = PxAbs(c0.x) + PxAbs(c1.x) + PxAbs(c2.x); + w.y = PxAbs(c0.y) + PxAbs(c1.y) + PxAbs(c2.y); + w.z = PxAbs(c0.z) + PxAbs(c1.z) + PxAbs(c2.z); + + return PxBounds3(center - w, center + w); +} + +PX_CUDA_CALLABLE PX_INLINE PxBounds3 PxBounds3::poseExtent(const PxTransform& pose, const PxVec3& extent) +{ + return basisExtent(pose.p, PxMat33(pose.q), extent); +} + +PX_CUDA_CALLABLE PX_FORCE_INLINE void PxBounds3::setEmpty() +{ + minimum = PxVec3(PX_MAX_BOUNDS_EXTENTS); + maximum = PxVec3(-PX_MAX_BOUNDS_EXTENTS); +} + +PX_CUDA_CALLABLE PX_FORCE_INLINE void PxBounds3::setMaximal() +{ + minimum = PxVec3(-PX_MAX_BOUNDS_EXTENTS); + maximum = PxVec3(PX_MAX_BOUNDS_EXTENTS); +} + +PX_CUDA_CALLABLE PX_FORCE_INLINE void PxBounds3::include(const PxVec3& v) +{ + PX_SHARED_ASSERT(isValid()); + minimum = minimum.minimum(v); + maximum = maximum.maximum(v); +} + +PX_CUDA_CALLABLE PX_FORCE_INLINE void PxBounds3::include(const PxBounds3& b) +{ + PX_SHARED_ASSERT(isValid()); + minimum = minimum.minimum(b.minimum); + maximum = maximum.maximum(b.maximum); +} + +PX_CUDA_CALLABLE PX_FORCE_INLINE bool PxBounds3::isEmpty() const +{ + PX_SHARED_ASSERT(isValid()); + return minimum.x > maximum.x; +} + +PX_CUDA_CALLABLE PX_FORCE_INLINE bool PxBounds3::intersects(const PxBounds3& b) const +{ + PX_SHARED_ASSERT(isValid() && b.isValid()); + return !(b.minimum.x > maximum.x || minimum.x > b.maximum.x || b.minimum.y > maximum.y || minimum.y > b.maximum.y || + b.minimum.z > maximum.z || minimum.z > b.maximum.z); +} + +PX_CUDA_CALLABLE PX_FORCE_INLINE bool PxBounds3::intersects1D(const PxBounds3& a, uint32_t axis) const +{ + PX_SHARED_ASSERT(isValid() && a.isValid()); + return maximum[axis] >= a.minimum[axis] && a.maximum[axis] >= minimum[axis]; +} + +PX_CUDA_CALLABLE PX_FORCE_INLINE bool PxBounds3::contains(const PxVec3& v) const +{ + PX_SHARED_ASSERT(isValid()); + + return !(v.x < minimum.x || v.x > maximum.x || v.y < minimum.y || v.y > maximum.y || v.z < minimum.z || + v.z > maximum.z); +} + +PX_CUDA_CALLABLE PX_FORCE_INLINE bool PxBounds3::isInside(const PxBounds3& box) const +{ + PX_SHARED_ASSERT(isValid() && box.isValid()); + if(box.minimum.x > minimum.x) + return false; + if(box.minimum.y > minimum.y) + return false; + if(box.minimum.z > minimum.z) + return false; + if(box.maximum.x < maximum.x) + return false; + if(box.maximum.y < maximum.y) + return false; + if(box.maximum.z < maximum.z) + return false; + return true; +} + +PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 PxBounds3::getCenter() const +{ + PX_SHARED_ASSERT(isValid()); + return (minimum + maximum) * 0.5f; +} + +PX_CUDA_CALLABLE PX_FORCE_INLINE float PxBounds3::getCenter(uint32_t axis) const +{ + PX_SHARED_ASSERT(isValid()); + return (minimum[axis] + maximum[axis]) * 0.5f; +} + +PX_CUDA_CALLABLE PX_FORCE_INLINE float PxBounds3::getExtents(uint32_t axis) const +{ + PX_SHARED_ASSERT(isValid()); + return (maximum[axis] - minimum[axis]) * 0.5f; +} + +PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 PxBounds3::getDimensions() const +{ + PX_SHARED_ASSERT(isValid()); + return maximum - minimum; +} + +PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 PxBounds3::getExtents() const +{ + PX_SHARED_ASSERT(isValid()); + return getDimensions() * 0.5f; +} + +PX_CUDA_CALLABLE PX_FORCE_INLINE void PxBounds3::scaleSafe(float scale) +{ + PX_SHARED_ASSERT(isValid()); + if(!isEmpty()) + scaleFast(scale); +} + +PX_CUDA_CALLABLE PX_FORCE_INLINE void PxBounds3::scaleFast(float scale) +{ + PX_SHARED_ASSERT(isValid()); + *this = centerExtents(getCenter(), getExtents() * scale); +} + +PX_CUDA_CALLABLE PX_FORCE_INLINE void PxBounds3::fattenSafe(float distance) +{ + PX_SHARED_ASSERT(isValid()); + if(!isEmpty()) + fattenFast(distance); +} + +PX_CUDA_CALLABLE PX_FORCE_INLINE void PxBounds3::fattenFast(float distance) +{ + PX_SHARED_ASSERT(isValid()); + minimum.x -= distance; + minimum.y -= distance; + minimum.z -= distance; + + maximum.x += distance; + maximum.y += distance; + maximum.z += distance; +} + +PX_CUDA_CALLABLE PX_INLINE PxBounds3 PxBounds3::transformSafe(const PxMat33& matrix, const PxBounds3& bounds) +{ + PX_SHARED_ASSERT(bounds.isValid()); + return !bounds.isEmpty() ? transformFast(matrix, bounds) : bounds; +} + +PX_CUDA_CALLABLE PX_INLINE PxBounds3 PxBounds3::transformFast(const PxMat33& matrix, const PxBounds3& bounds) +{ + PX_SHARED_ASSERT(bounds.isValid()); + return PxBounds3::basisExtent(matrix * bounds.getCenter(), matrix, bounds.getExtents()); +} + +PX_CUDA_CALLABLE PX_INLINE PxBounds3 PxBounds3::transformSafe(const PxTransform& transform, const PxBounds3& bounds) +{ + PX_SHARED_ASSERT(bounds.isValid()); + return !bounds.isEmpty() ? transformFast(transform, bounds) : bounds; +} + +PX_CUDA_CALLABLE PX_INLINE PxBounds3 PxBounds3::transformFast(const PxTransform& transform, const PxBounds3& bounds) +{ + PX_SHARED_ASSERT(bounds.isValid()); + return PxBounds3::basisExtent(transform.transform(bounds.getCenter()), PxMat33(transform.q), bounds.getExtents()); +} + +PX_CUDA_CALLABLE PX_FORCE_INLINE bool PxBounds3::isValid() const +{ + return (isFinite() && (((minimum.x <= maximum.x) && (minimum.y <= maximum.y) && (minimum.z <= maximum.z)) || + ((minimum.x == PX_MAX_BOUNDS_EXTENTS) && (minimum.y == PX_MAX_BOUNDS_EXTENTS) && + (minimum.z == PX_MAX_BOUNDS_EXTENTS) && (maximum.x == -PX_MAX_BOUNDS_EXTENTS) && + (maximum.y == -PX_MAX_BOUNDS_EXTENTS) && (maximum.z == -PX_MAX_BOUNDS_EXTENTS)))); +} + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif // #ifndef PXFOUNDATION_PXBOUNDS3_H diff --git a/sources/PhysX/PxShared/include/foundation/PxErrorCallback.h b/sources/PhysX/PxShared/include/foundation/PxErrorCallback.h new file mode 100644 index 00000000..c0517dbe --- /dev/null +++ b/sources/PhysX/PxShared/include/foundation/PxErrorCallback.h @@ -0,0 +1,73 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PXFOUNDATION_PXERRORCALLBACK_H +#define PXFOUNDATION_PXERRORCALLBACK_H + +/** \addtogroup foundation +@{ +*/ + +#include "foundation/PxErrors.h" +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief User defined interface class. Used by the library to emit debug information. + +\note The SDK state should not be modified from within any error reporting functions. + +Threading: The SDK sequences its calls to the output stream using a mutex, so the class need not +be implemented in a thread-safe manner if the SDK is the only client. +*/ +class PxErrorCallback +{ + public: + virtual ~PxErrorCallback() + { + } + + /** + \brief Reports an error code. + \param code Error code, see #PxErrorCode + \param message Message to display. + \param file File error occured in. + \param line Line number error occured on. + */ + virtual void reportError(PxErrorCode::Enum code, const char* message, const char* file, int line) = 0; +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif // #ifndef PXFOUNDATION_PXERRORCALLBACK_H diff --git a/sources/PhysX/PxShared/include/foundation/PxErrors.h b/sources/PhysX/PxShared/include/foundation/PxErrors.h new file mode 100644 index 00000000..cf86d3ba --- /dev/null +++ b/sources/PhysX/PxShared/include/foundation/PxErrors.h @@ -0,0 +1,93 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PXFOUNDATION_PXERRORS_H +#define PXFOUNDATION_PXERRORS_H +/** \addtogroup foundation +@{ +*/ + +#include "foundation/Px.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief Error codes + +These error codes are passed to #PxErrorCallback + +@see PxErrorCallback +*/ + +struct PxErrorCode +{ + enum Enum + { + eNO_ERROR = 0, + + //! \brief An informational message. + eDEBUG_INFO = 1, + + //! \brief a warning message for the user to help with debugging + eDEBUG_WARNING = 2, + + //! \brief method called with invalid parameter(s) + eINVALID_PARAMETER = 4, + + //! \brief method was called at a time when an operation is not possible + eINVALID_OPERATION = 8, + + //! \brief method failed to allocate some memory + eOUT_OF_MEMORY = 16, + + /** \brief The library failed for some reason. + Possibly you have passed invalid values like NaNs, which are not checked for. + */ + eINTERNAL_ERROR = 32, + + //! \brief An unrecoverable error, execution should be halted and log output flushed + eABORT = 64, + + //! \brief The SDK has determined that an operation may result in poor performance. + ePERF_WARNING = 128, + + //! \brief A bit mask for including all errors + eMASK_ALL = -1 + }; +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif // #ifndef PXFOUNDATION_PXERRORS_H diff --git a/sources/PhysX/PxShared/include/foundation/PxFlags.h b/sources/PhysX/PxShared/include/foundation/PxFlags.h new file mode 100644 index 00000000..85dce4ed --- /dev/null +++ b/sources/PhysX/PxShared/include/foundation/PxFlags.h @@ -0,0 +1,376 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PXFOUNDATION_PXFLAGS_H +#define PXFOUNDATION_PXFLAGS_H + +/** \addtogroup foundation + @{ +*/ + +#include "foundation/Px.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif +/** +\brief Container for bitfield flag variables associated with a specific enum type. + +This allows for type safe manipulation for bitfields. + +

Example

+ // enum that defines each bit... + struct MyEnum + { + enum Enum + { + eMAN = 1, + eBEAR = 2, + ePIG = 4, + }; + }; + + // implements some convenient global operators. + PX_FLAGS_OPERATORS(MyEnum::Enum, uint8_t); + + PxFlags myFlags; + myFlags |= MyEnum::eMAN; + myFlags |= MyEnum::eBEAR | MyEnum::ePIG; + if(myFlags & MyEnum::eBEAR) + { + doSomething(); + } +*/ + +template +class PxFlags +{ + public: + typedef storagetype InternalType; + + PX_CUDA_CALLABLE PX_INLINE explicit PxFlags(const PxEMPTY) + { + } + PX_CUDA_CALLABLE PX_INLINE PxFlags(void); + PX_CUDA_CALLABLE PX_INLINE PxFlags(enumtype e); + PX_CUDA_CALLABLE PX_INLINE PxFlags(const PxFlags& f); + PX_CUDA_CALLABLE PX_INLINE explicit PxFlags(storagetype b); + + PX_CUDA_CALLABLE PX_INLINE bool isSet(enumtype e) const; + PX_CUDA_CALLABLE PX_INLINE PxFlags& set(enumtype e); + PX_CUDA_CALLABLE PX_INLINE bool operator==(enumtype e) const; + PX_CUDA_CALLABLE PX_INLINE bool operator==(const PxFlags& f) const; + PX_CUDA_CALLABLE PX_INLINE bool operator==(bool b) const; + PX_CUDA_CALLABLE PX_INLINE bool operator!=(enumtype e) const; + PX_CUDA_CALLABLE PX_INLINE bool operator!=(const PxFlags& f) const; + + PX_CUDA_CALLABLE PX_INLINE PxFlags& operator=(const PxFlags& f); + PX_CUDA_CALLABLE PX_INLINE PxFlags& operator=(enumtype e); + + PX_CUDA_CALLABLE PX_INLINE PxFlags& operator|=(enumtype e); + PX_CUDA_CALLABLE PX_INLINE PxFlags& operator|=(const PxFlags& f); + PX_CUDA_CALLABLE PX_INLINE PxFlags operator|(enumtype e) const; + PX_CUDA_CALLABLE PX_INLINE PxFlags operator|(const PxFlags& f) const; + + PX_CUDA_CALLABLE PX_INLINE PxFlags& operator&=(enumtype e); + PX_CUDA_CALLABLE PX_INLINE PxFlags& operator&=(const PxFlags& f); + PX_CUDA_CALLABLE PX_INLINE PxFlags operator&(enumtype e) const; + PX_CUDA_CALLABLE PX_INLINE PxFlags operator&(const PxFlags& f) const; + + PX_CUDA_CALLABLE PX_INLINE PxFlags& operator^=(enumtype e); + PX_CUDA_CALLABLE PX_INLINE PxFlags& operator^=(const PxFlags& f); + PX_CUDA_CALLABLE PX_INLINE PxFlags operator^(enumtype e) const; + PX_CUDA_CALLABLE PX_INLINE PxFlags operator^(const PxFlags& f) const; + + PX_CUDA_CALLABLE PX_INLINE PxFlags operator~(void) const; + + PX_CUDA_CALLABLE PX_INLINE operator bool(void) const; + PX_CUDA_CALLABLE PX_INLINE operator uint8_t(void) const; + PX_CUDA_CALLABLE PX_INLINE operator uint16_t(void) const; + PX_CUDA_CALLABLE PX_INLINE operator uint32_t(void) const; + + PX_CUDA_CALLABLE PX_INLINE void clear(enumtype e); + + public: + friend PX_INLINE PxFlags operator&(enumtype a, PxFlags& b) + { + PxFlags out; + out.mBits = a & b.mBits; + return out; + } + + private: + storagetype mBits; +}; + +#if !PX_DOXYGEN + +#define PX_FLAGS_OPERATORS(enumtype, storagetype) \ + PX_CUDA_CALLABLE PX_INLINE PxFlags operator|(enumtype a, enumtype b) \ + { \ + PxFlags r(a); \ + r |= b; \ + return r; \ + } \ + PX_CUDA_CALLABLE PX_INLINE PxFlags operator&(enumtype a, enumtype b) \ + { \ + PxFlags r(a); \ + r &= b; \ + return r; \ + } \ + PX_CUDA_CALLABLE PX_INLINE PxFlags operator~(enumtype a) \ + { \ + return ~PxFlags(a); \ + } + +#define PX_FLAGS_TYPEDEF(x, y) \ + typedef PxFlags x##s; \ + PX_FLAGS_OPERATORS(x::Enum, y) + +template +PX_CUDA_CALLABLE PX_INLINE PxFlags::PxFlags(void) +{ + mBits = 0; +} + +template +PX_CUDA_CALLABLE PX_INLINE PxFlags::PxFlags(enumtype e) +{ + mBits = static_cast(e); +} + +template +PX_CUDA_CALLABLE PX_INLINE PxFlags::PxFlags(const PxFlags& f) +{ + mBits = f.mBits; +} + +template +PX_CUDA_CALLABLE PX_INLINE PxFlags::PxFlags(storagetype b) +{ + mBits = b; +} + +template +PX_CUDA_CALLABLE PX_INLINE bool PxFlags::isSet(enumtype e) const +{ + return (mBits & static_cast(e)) == static_cast(e); +} + +template +PX_CUDA_CALLABLE PX_INLINE PxFlags& PxFlags::set(enumtype e) +{ + mBits = static_cast(e); + return *this; +} + +template +PX_CUDA_CALLABLE PX_INLINE bool PxFlags::operator==(enumtype e) const +{ + return mBits == static_cast(e); +} + +template +PX_CUDA_CALLABLE PX_INLINE bool PxFlags::operator==(const PxFlags& f) const +{ + return mBits == f.mBits; +} + +template +PX_CUDA_CALLABLE PX_INLINE bool PxFlags::operator==(bool b) const +{ + return bool(*this) == b; +} + +template +PX_CUDA_CALLABLE PX_INLINE bool PxFlags::operator!=(enumtype e) const +{ + return mBits != static_cast(e); +} + +template +PX_CUDA_CALLABLE PX_INLINE bool PxFlags::operator!=(const PxFlags& f) const +{ + return mBits != f.mBits; +} + +template +PX_CUDA_CALLABLE PX_INLINE PxFlags& PxFlags::operator=(enumtype e) +{ + mBits = static_cast(e); + return *this; +} + +template +PX_CUDA_CALLABLE PX_INLINE PxFlags& PxFlags::operator=(const PxFlags& f) +{ + mBits = f.mBits; + return *this; +} + +template +PX_CUDA_CALLABLE PX_INLINE PxFlags& PxFlags::operator|=(enumtype e) +{ + mBits |= static_cast(e); + return *this; +} + +template +PX_CUDA_CALLABLE PX_INLINE PxFlags& PxFlags:: +operator|=(const PxFlags& f) +{ + mBits |= f.mBits; + return *this; +} + +template +PX_CUDA_CALLABLE PX_INLINE PxFlags PxFlags::operator|(enumtype e) const +{ + PxFlags out(*this); + out |= e; + return out; +} + +template +PX_CUDA_CALLABLE PX_INLINE PxFlags PxFlags:: +operator|(const PxFlags& f) const +{ + PxFlags out(*this); + out |= f; + return out; +} + +template +PX_CUDA_CALLABLE PX_INLINE PxFlags& PxFlags::operator&=(enumtype e) +{ + mBits &= static_cast(e); + return *this; +} + +template +PX_CUDA_CALLABLE PX_INLINE PxFlags& PxFlags:: +operator&=(const PxFlags& f) +{ + mBits &= f.mBits; + return *this; +} + +template +PX_CUDA_CALLABLE PX_INLINE PxFlags PxFlags::operator&(enumtype e) const +{ + PxFlags out = *this; + out.mBits &= static_cast(e); + return out; +} + +template +PX_CUDA_CALLABLE PX_INLINE PxFlags PxFlags:: +operator&(const PxFlags& f) const +{ + PxFlags out = *this; + out.mBits &= f.mBits; + return out; +} + +template +PX_CUDA_CALLABLE PX_INLINE PxFlags& PxFlags::operator^=(enumtype e) +{ + mBits ^= static_cast(e); + return *this; +} + +template +PX_CUDA_CALLABLE PX_INLINE PxFlags& PxFlags:: +operator^=(const PxFlags& f) +{ + mBits ^= f.mBits; + return *this; +} + +template +PX_CUDA_CALLABLE PX_INLINE PxFlags PxFlags::operator^(enumtype e) const +{ + PxFlags out = *this; + out.mBits ^= static_cast(e); + return out; +} + +template +PX_CUDA_CALLABLE PX_INLINE PxFlags PxFlags:: +operator^(const PxFlags& f) const +{ + PxFlags out = *this; + out.mBits ^= f.mBits; + return out; +} + +template +PX_CUDA_CALLABLE PX_INLINE PxFlags PxFlags::operator~(void) const +{ + PxFlags out; + out.mBits = storagetype(~mBits); + return out; +} + +template +PX_CUDA_CALLABLE PX_INLINE PxFlags::operator bool(void) const +{ + return mBits ? true : false; +} + +template +PX_CUDA_CALLABLE PX_INLINE PxFlags::operator uint8_t(void) const +{ + return static_cast(mBits); +} + +template +PX_CUDA_CALLABLE PX_INLINE PxFlags::operator uint16_t(void) const +{ + return static_cast(mBits); +} + +template +PX_CUDA_CALLABLE PX_INLINE PxFlags::operator uint32_t(void) const +{ + return static_cast(mBits); +} + +template +PX_CUDA_CALLABLE PX_INLINE void PxFlags::clear(enumtype e) +{ + mBits &= ~static_cast(e); +} + +} // namespace physx +#endif //!PX_DOXYGEN + +/** @} */ +#endif // #ifndef PXFOUNDATION_PXFLAGS_H diff --git a/sources/PhysX/PxShared/include/foundation/PxIO.h b/sources/PhysX/PxShared/include/foundation/PxIO.h new file mode 100644 index 00000000..1db6a805 --- /dev/null +++ b/sources/PhysX/PxShared/include/foundation/PxIO.h @@ -0,0 +1,138 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PXFOUNDATION_PXIO_H +#define PXFOUNDATION_PXIO_H + +/** \addtogroup common + @{ +*/ + +#include "foundation/PxSimpleTypes.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief Input stream class for I/O. + +The user needs to supply a PxInputStream implementation to a number of methods to allow the SDK to read data. +*/ + +class PxInputStream +{ + public: + /** + \brief read from the stream. The number of bytes read may be less than the number requested. + + \param[in] dest the destination address to which the data will be read + \param[in] count the number of bytes requested + + \return the number of bytes read from the stream. + */ + + virtual uint32_t read(void* dest, uint32_t count) = 0; + + virtual ~PxInputStream() + { + } +}; + +/** +\brief Input data class for I/O which provides random read access. + +The user needs to supply a PxInputData implementation to a number of methods to allow the SDK to read data. +*/ + +class PxInputData : public PxInputStream +{ + public: + /** + \brief return the length of the input data + + \return size in bytes of the input data + */ + + virtual uint32_t getLength() const = 0; + + /** + \brief seek to the given offset from the start of the data. + + \param[in] offset the offset to seek to. If greater than the length of the data, this call is equivalent to + seek(length); + */ + + virtual void seek(uint32_t offset) = 0; + + /** + \brief return the current offset from the start of the data + + \return the offset to seek to. + */ + + virtual uint32_t tell() const = 0; + + virtual ~PxInputData() + { + } +}; + +/** +\brief Output stream class for I/O. + +The user needs to supply a PxOutputStream implementation to a number of methods to allow the SDK to write data. +*/ + +class PxOutputStream +{ + public: + /** + \brief write to the stream. The number of bytes written may be less than the number sent. + + \param[in] src the destination address from which the data will be written + \param[in] count the number of bytes to be written + + \return the number of bytes written to the stream by this call. + */ + + virtual uint32_t write(const void* src, uint32_t count) = 0; + + virtual ~PxOutputStream() + { + } +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif // #ifndef PXFOUNDATION_PXIO_H diff --git a/sources/PhysX/PxShared/include/foundation/PxIntrinsics.h b/sources/PhysX/PxShared/include/foundation/PxIntrinsics.h new file mode 100644 index 00000000..8ddea2a0 --- /dev/null +++ b/sources/PhysX/PxShared/include/foundation/PxIntrinsics.h @@ -0,0 +1,47 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PXFOUNDATION_PXINTRINSICS_H +#define PXFOUNDATION_PXINTRINSICS_H + +#include "foundation/PxPreprocessor.h" + +#if PX_WINDOWS_FAMILY +#include "foundation/windows/PxWindowsIntrinsics.h" +#elif(PX_LINUX || PX_ANDROID || PX_APPLE_FAMILY || PX_PS4) +#include "foundation/unix/PxUnixIntrinsics.h" +#elif PX_XBOXONE +#include "foundation/XboxOne/PxXboxOneIntrinsics.h" +#elif PX_SWITCH +#include "foundation/switch/PxSwitchIntrinsics.h" +#else +#error "Platform not supported!" +#endif + +#endif // #ifndef PXFOUNDATION_PXINTRINSICS_H diff --git a/sources/PhysX/PxShared/include/foundation/PxMat33.h b/sources/PhysX/PxShared/include/foundation/PxMat33.h new file mode 100644 index 00000000..3019ba2d --- /dev/null +++ b/sources/PhysX/PxShared/include/foundation/PxMat33.h @@ -0,0 +1,396 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PXFOUNDATION_PXMAT33_H +#define PXFOUNDATION_PXMAT33_H +/** \addtogroup foundation +@{ +*/ + +#include "foundation/PxVec3.h" +#include "foundation/PxQuat.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif +/*! +\brief 3x3 matrix class + +Some clarifications, as there have been much confusion about matrix formats etc in the past. + +Short: +- Matrix have base vectors in columns (vectors are column matrices, 3x1 matrices). +- Matrix is physically stored in column major format +- Matrices are concaternated from left + +Long: +Given three base vectors a, b and c the matrix is stored as + +|a.x b.x c.x| +|a.y b.y c.y| +|a.z b.z c.z| + +Vectors are treated as columns, so the vector v is + +|x| +|y| +|z| + +And matrices are applied _before_ the vector (pre-multiplication) +v' = M*v + +|x'| |a.x b.x c.x| |x| |a.x*x + b.x*y + c.x*z| +|y'| = |a.y b.y c.y| * |y| = |a.y*x + b.y*y + c.y*z| +|z'| |a.z b.z c.z| |z| |a.z*x + b.z*y + c.z*z| + + +Physical storage and indexing: +To be compatible with popular 3d rendering APIs (read D3d and OpenGL) +the physical indexing is + +|0 3 6| +|1 4 7| +|2 5 8| + +index = column*3 + row + +which in C++ translates to M[column][row] + +The mathematical indexing is M_row,column and this is what is used for _-notation +so _12 is 1st row, second column and operator(row, column)! + +*/ +class PxMat33 +{ + public: + //! Default constructor + PX_CUDA_CALLABLE PX_FORCE_INLINE PxMat33() + { + } + + //! identity constructor + PX_CUDA_CALLABLE PX_INLINE PxMat33(PxIDENTITY r) + : column0(1.0f, 0.0f, 0.0f), column1(0.0f, 1.0f, 0.0f), column2(0.0f, 0.0f, 1.0f) + { + PX_UNUSED(r); + } + + //! zero constructor + PX_CUDA_CALLABLE PX_INLINE PxMat33(PxZERO r) : column0(0.0f), column1(0.0f), column2(0.0f) + { + PX_UNUSED(r); + } + + //! Construct from three base vectors + PX_CUDA_CALLABLE PxMat33(const PxVec3& col0, const PxVec3& col1, const PxVec3& col2) + : column0(col0), column1(col1), column2(col2) + { + } + + //! constructor from a scalar, which generates a multiple of the identity matrix + explicit PX_CUDA_CALLABLE PX_INLINE PxMat33(float r) + : column0(r, 0.0f, 0.0f), column1(0.0f, r, 0.0f), column2(0.0f, 0.0f, r) + { + } + + //! Construct from float[9] + explicit PX_CUDA_CALLABLE PX_INLINE PxMat33(float values[]) + : column0(values[0], values[1], values[2]) + , column1(values[3], values[4], values[5]) + , column2(values[6], values[7], values[8]) + { + } + + //! Construct from a quaternion + explicit PX_CUDA_CALLABLE PX_FORCE_INLINE PxMat33(const PxQuat& q) + { + const float x = q.x; + const float y = q.y; + const float z = q.z; + const float w = q.w; + + const float x2 = x + x; + const float y2 = y + y; + const float z2 = z + z; + + const float xx = x2 * x; + const float yy = y2 * y; + const float zz = z2 * z; + + const float xy = x2 * y; + const float xz = x2 * z; + const float xw = x2 * w; + + const float yz = y2 * z; + const float yw = y2 * w; + const float zw = z2 * w; + + column0 = PxVec3(1.0f - yy - zz, xy + zw, xz - yw); + column1 = PxVec3(xy - zw, 1.0f - xx - zz, yz + xw); + column2 = PxVec3(xz + yw, yz - xw, 1.0f - xx - yy); + } + + //! Copy constructor + PX_CUDA_CALLABLE PX_INLINE PxMat33(const PxMat33& other) + : column0(other.column0), column1(other.column1), column2(other.column2) + { + } + + //! Assignment operator + PX_CUDA_CALLABLE PX_FORCE_INLINE PxMat33& operator=(const PxMat33& other) + { + column0 = other.column0; + column1 = other.column1; + column2 = other.column2; + return *this; + } + + //! Construct from diagonal, off-diagonals are zero. + PX_CUDA_CALLABLE PX_INLINE static const PxMat33 createDiagonal(const PxVec3& d) + { + return PxMat33(PxVec3(d.x, 0.0f, 0.0f), PxVec3(0.0f, d.y, 0.0f), PxVec3(0.0f, 0.0f, d.z)); + } + + /** + \brief returns true if the two matrices are exactly equal + */ + PX_CUDA_CALLABLE PX_INLINE bool operator==(const PxMat33& m) const + { + return column0 == m.column0 && column1 == m.column1 && column2 == m.column2; + } + + //! Get transposed matrix + PX_CUDA_CALLABLE PX_FORCE_INLINE const PxMat33 getTranspose() const + { + const PxVec3 v0(column0.x, column1.x, column2.x); + const PxVec3 v1(column0.y, column1.y, column2.y); + const PxVec3 v2(column0.z, column1.z, column2.z); + + return PxMat33(v0, v1, v2); + } + + //! Get the real inverse + PX_CUDA_CALLABLE PX_INLINE const PxMat33 getInverse() const + { + const float det = getDeterminant(); + PxMat33 inverse; + + if(det != 0) + { + const float invDet = 1.0f / det; + + inverse.column0.x = invDet * (column1.y * column2.z - column2.y * column1.z); + inverse.column0.y = invDet * -(column0.y * column2.z - column2.y * column0.z); + inverse.column0.z = invDet * (column0.y * column1.z - column0.z * column1.y); + + inverse.column1.x = invDet * -(column1.x * column2.z - column1.z * column2.x); + inverse.column1.y = invDet * (column0.x * column2.z - column0.z * column2.x); + inverse.column1.z = invDet * -(column0.x * column1.z - column0.z * column1.x); + + inverse.column2.x = invDet * (column1.x * column2.y - column1.y * column2.x); + inverse.column2.y = invDet * -(column0.x * column2.y - column0.y * column2.x); + inverse.column2.z = invDet * (column0.x * column1.y - column1.x * column0.y); + + return inverse; + } + else + { + return PxMat33(PxIdentity); + } + } + + //! Get determinant + PX_CUDA_CALLABLE PX_INLINE float getDeterminant() const + { + return column0.dot(column1.cross(column2)); + } + + //! Unary minus + PX_CUDA_CALLABLE PX_INLINE const PxMat33 operator-() const + { + return PxMat33(-column0, -column1, -column2); + } + + //! Add + PX_CUDA_CALLABLE PX_INLINE const PxMat33 operator+(const PxMat33& other) const + { + return PxMat33(column0 + other.column0, column1 + other.column1, column2 + other.column2); + } + + //! Subtract + PX_CUDA_CALLABLE PX_INLINE const PxMat33 operator-(const PxMat33& other) const + { + return PxMat33(column0 - other.column0, column1 - other.column1, column2 - other.column2); + } + + //! Scalar multiplication + PX_CUDA_CALLABLE PX_INLINE const PxMat33 operator*(float scalar) const + { + return PxMat33(column0 * scalar, column1 * scalar, column2 * scalar); + } + + friend PxMat33 operator*(float, const PxMat33&); + + //! Matrix vector multiplication (returns 'this->transform(vec)') + PX_CUDA_CALLABLE PX_INLINE const PxVec3 operator*(const PxVec3& vec) const + { + return transform(vec); + } + + // a = b operators + + //! Matrix multiplication + PX_CUDA_CALLABLE PX_FORCE_INLINE const PxMat33 operator*(const PxMat33& other) const + { + // Rows from this columns from other + // column0 = transform(other.column0) etc + return PxMat33(transform(other.column0), transform(other.column1), transform(other.column2)); + } + + //! Equals-add + PX_CUDA_CALLABLE PX_INLINE PxMat33& operator+=(const PxMat33& other) + { + column0 += other.column0; + column1 += other.column1; + column2 += other.column2; + return *this; + } + + //! Equals-sub + PX_CUDA_CALLABLE PX_INLINE PxMat33& operator-=(const PxMat33& other) + { + column0 -= other.column0; + column1 -= other.column1; + column2 -= other.column2; + return *this; + } + + //! Equals scalar multiplication + PX_CUDA_CALLABLE PX_INLINE PxMat33& operator*=(float scalar) + { + column0 *= scalar; + column1 *= scalar; + column2 *= scalar; + return *this; + } + + //! Equals matrix multiplication + PX_CUDA_CALLABLE PX_INLINE PxMat33& operator*=(const PxMat33& other) + { + *this = *this * other; + return *this; + } + + //! Element access, mathematical way! + PX_CUDA_CALLABLE PX_FORCE_INLINE float operator()(unsigned int row, unsigned int col) const + { + return (*this)[col][row]; + } + + //! Element access, mathematical way! + PX_CUDA_CALLABLE PX_FORCE_INLINE float& operator()(unsigned int row, unsigned int col) + { + return (*this)[col][row]; + } + + // Transform etc + + //! Transform vector by matrix, equal to v' = M*v + PX_CUDA_CALLABLE PX_FORCE_INLINE const PxVec3 transform(const PxVec3& other) const + { + return column0 * other.x + column1 * other.y + column2 * other.z; + } + + //! Transform vector by matrix transpose, v' = M^t*v + PX_CUDA_CALLABLE PX_INLINE const PxVec3 transformTranspose(const PxVec3& other) const + { + return PxVec3(column0.dot(other), column1.dot(other), column2.dot(other)); + } + + PX_CUDA_CALLABLE PX_FORCE_INLINE const float* front() const + { + return &column0.x; + } + + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3& operator[](unsigned int num) + { + return (&column0)[num]; + } + PX_CUDA_CALLABLE PX_FORCE_INLINE const PxVec3& operator[](unsigned int num) const + { + return (&column0)[num]; + } + + // Data, see above for format! + + PxVec3 column0, column1, column2; // the three base vectors +}; + +// implementation from PxQuat.h +PX_CUDA_CALLABLE PX_INLINE PxQuat::PxQuat(const PxMat33& m) +{ + if(m.column2.z < 0) + { + if(m.column0.x > m.column1.y) + { + float t = 1 + m.column0.x - m.column1.y - m.column2.z; + *this = PxQuat(t, m.column0.y + m.column1.x, m.column2.x + m.column0.z, m.column1.z - m.column2.y) * + (0.5f / PxSqrt(t)); + } + else + { + float t = 1 - m.column0.x + m.column1.y - m.column2.z; + *this = PxQuat(m.column0.y + m.column1.x, t, m.column1.z + m.column2.y, m.column2.x - m.column0.z) * + (0.5f / PxSqrt(t)); + } + } + else + { + if(m.column0.x < -m.column1.y) + { + float t = 1 - m.column0.x - m.column1.y + m.column2.z; + *this = PxQuat(m.column2.x + m.column0.z, m.column1.z + m.column2.y, t, m.column0.y - m.column1.x) * + (0.5f / PxSqrt(t)); + } + else + { + float t = 1 + m.column0.x + m.column1.y + m.column2.z; + *this = PxQuat(m.column1.z - m.column2.y, m.column2.x - m.column0.z, m.column0.y - m.column1.x, t) * + (0.5f / PxSqrt(t)); + } + } +} + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif // #ifndef PXFOUNDATION_PXMAT33_H diff --git a/sources/PhysX/PxShared/include/foundation/PxMat44.h b/sources/PhysX/PxShared/include/foundation/PxMat44.h new file mode 100644 index 00000000..577a93fb --- /dev/null +++ b/sources/PhysX/PxShared/include/foundation/PxMat44.h @@ -0,0 +1,376 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PXFOUNDATION_PXMAT44_H +#define PXFOUNDATION_PXMAT44_H +/** \addtogroup foundation +@{ +*/ + +#include "foundation/PxQuat.h" +#include "foundation/PxVec4.h" +#include "foundation/PxMat33.h" +#include "foundation/PxTransform.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/*! +\brief 4x4 matrix class + +This class is layout-compatible with D3D and OpenGL matrices. More notes on layout are given in the PxMat33 + +@see PxMat33 PxTransform +*/ + +class PxMat44 +{ + public: + //! Default constructor + PX_CUDA_CALLABLE PX_INLINE PxMat44() + { + } + + //! identity constructor + PX_CUDA_CALLABLE PX_INLINE PxMat44(PxIDENTITY r) + : column0(1.0f, 0.0f, 0.0f, 0.0f) + , column1(0.0f, 1.0f, 0.0f, 0.0f) + , column2(0.0f, 0.0f, 1.0f, 0.0f) + , column3(0.0f, 0.0f, 0.0f, 1.0f) + { + PX_UNUSED(r); + } + + //! zero constructor + PX_CUDA_CALLABLE PX_INLINE PxMat44(PxZERO r) : column0(PxZero), column1(PxZero), column2(PxZero), column3(PxZero) + { + PX_UNUSED(r); + } + + //! Construct from four 4-vectors + PX_CUDA_CALLABLE PxMat44(const PxVec4& col0, const PxVec4& col1, const PxVec4& col2, const PxVec4& col3) + : column0(col0), column1(col1), column2(col2), column3(col3) + { + } + + //! constructor that generates a multiple of the identity matrix + explicit PX_CUDA_CALLABLE PX_INLINE PxMat44(float r) + : column0(r, 0.0f, 0.0f, 0.0f) + , column1(0.0f, r, 0.0f, 0.0f) + , column2(0.0f, 0.0f, r, 0.0f) + , column3(0.0f, 0.0f, 0.0f, r) + { + } + + //! Construct from three base vectors and a translation + PX_CUDA_CALLABLE PxMat44(const PxVec3& col0, const PxVec3& col1, const PxVec3& col2, const PxVec3& col3) + : column0(col0, 0), column1(col1, 0), column2(col2, 0), column3(col3, 1.0f) + { + } + + //! Construct from float[16] + explicit PX_CUDA_CALLABLE PX_INLINE PxMat44(float values[]) + : column0(values[0], values[1], values[2], values[3]) + , column1(values[4], values[5], values[6], values[7]) + , column2(values[8], values[9], values[10], values[11]) + , column3(values[12], values[13], values[14], values[15]) + { + } + + //! Construct from a quaternion + explicit PX_CUDA_CALLABLE PX_INLINE PxMat44(const PxQuat& q) + { + const float x = q.x; + const float y = q.y; + const float z = q.z; + const float w = q.w; + + const float x2 = x + x; + const float y2 = y + y; + const float z2 = z + z; + + const float xx = x2 * x; + const float yy = y2 * y; + const float zz = z2 * z; + + const float xy = x2 * y; + const float xz = x2 * z; + const float xw = x2 * w; + + const float yz = y2 * z; + const float yw = y2 * w; + const float zw = z2 * w; + + column0 = PxVec4(1.0f - yy - zz, xy + zw, xz - yw, 0.0f); + column1 = PxVec4(xy - zw, 1.0f - xx - zz, yz + xw, 0.0f); + column2 = PxVec4(xz + yw, yz - xw, 1.0f - xx - yy, 0.0f); + column3 = PxVec4(0.0f, 0.0f, 0.0f, 1.0f); + } + + //! Construct from a diagonal vector + explicit PX_CUDA_CALLABLE PX_INLINE PxMat44(const PxVec4& diagonal) + : column0(diagonal.x, 0.0f, 0.0f, 0.0f) + , column1(0.0f, diagonal.y, 0.0f, 0.0f) + , column2(0.0f, 0.0f, diagonal.z, 0.0f) + , column3(0.0f, 0.0f, 0.0f, diagonal.w) + { + } + + //! Construct from Mat33 and a translation + PX_CUDA_CALLABLE PxMat44(const PxMat33& axes, const PxVec3& position) + : column0(axes.column0, 0.0f), column1(axes.column1, 0.0f), column2(axes.column2, 0.0f), column3(position, 1.0f) + { + } + + PX_CUDA_CALLABLE PxMat44(const PxTransform& t) + { + *this = PxMat44(PxMat33(t.q), t.p); + } + + /** + \brief returns true if the two matrices are exactly equal + */ + PX_CUDA_CALLABLE PX_INLINE bool operator==(const PxMat44& m) const + { + return column0 == m.column0 && column1 == m.column1 && column2 == m.column2 && column3 == m.column3; + } + + //! Copy constructor + PX_CUDA_CALLABLE PX_INLINE PxMat44(const PxMat44& other) + : column0(other.column0), column1(other.column1), column2(other.column2), column3(other.column3) + { + } + + //! Assignment operator + PX_CUDA_CALLABLE PX_INLINE PxMat44& operator=(const PxMat44& other) + { + column0 = other.column0; + column1 = other.column1; + column2 = other.column2; + column3 = other.column3; + return *this; + } + + //! Get transposed matrix + PX_CUDA_CALLABLE PX_INLINE const PxMat44 getTranspose() const + { + return PxMat44( + PxVec4(column0.x, column1.x, column2.x, column3.x), PxVec4(column0.y, column1.y, column2.y, column3.y), + PxVec4(column0.z, column1.z, column2.z, column3.z), PxVec4(column0.w, column1.w, column2.w, column3.w)); + } + + //! Unary minus + PX_CUDA_CALLABLE PX_INLINE const PxMat44 operator-() const + { + return PxMat44(-column0, -column1, -column2, -column3); + } + + //! Add + PX_CUDA_CALLABLE PX_INLINE const PxMat44 operator+(const PxMat44& other) const + { + return PxMat44(column0 + other.column0, column1 + other.column1, column2 + other.column2, + column3 + other.column3); + } + + //! Subtract + PX_CUDA_CALLABLE PX_INLINE const PxMat44 operator-(const PxMat44& other) const + { + return PxMat44(column0 - other.column0, column1 - other.column1, column2 - other.column2, + column3 - other.column3); + } + + //! Scalar multiplication + PX_CUDA_CALLABLE PX_INLINE const PxMat44 operator*(float scalar) const + { + return PxMat44(column0 * scalar, column1 * scalar, column2 * scalar, column3 * scalar); + } + + friend PxMat44 operator*(float, const PxMat44&); + + //! Matrix multiplication + PX_CUDA_CALLABLE PX_INLINE const PxMat44 operator*(const PxMat44& other) const + { + // Rows from this columns from other + // column0 = transform(other.column0) etc + return PxMat44(transform(other.column0), transform(other.column1), transform(other.column2), + transform(other.column3)); + } + + // a = b operators + + //! Equals-add + PX_CUDA_CALLABLE PX_INLINE PxMat44& operator+=(const PxMat44& other) + { + column0 += other.column0; + column1 += other.column1; + column2 += other.column2; + column3 += other.column3; + return *this; + } + + //! Equals-sub + PX_CUDA_CALLABLE PX_INLINE PxMat44& operator-=(const PxMat44& other) + { + column0 -= other.column0; + column1 -= other.column1; + column2 -= other.column2; + column3 -= other.column3; + return *this; + } + + //! Equals scalar multiplication + PX_CUDA_CALLABLE PX_INLINE PxMat44& operator*=(float scalar) + { + column0 *= scalar; + column1 *= scalar; + column2 *= scalar; + column3 *= scalar; + return *this; + } + + //! Equals matrix multiplication + PX_CUDA_CALLABLE PX_INLINE PxMat44& operator*=(const PxMat44& other) + { + *this = *this * other; + return *this; + } + + //! Element access, mathematical way! + PX_CUDA_CALLABLE PX_FORCE_INLINE float operator()(unsigned int row, unsigned int col) const + { + return (*this)[col][row]; + } + + //! Element access, mathematical way! + PX_CUDA_CALLABLE PX_FORCE_INLINE float& operator()(unsigned int row, unsigned int col) + { + return (*this)[col][row]; + } + + //! Transform vector by matrix, equal to v' = M*v + PX_CUDA_CALLABLE PX_INLINE const PxVec4 transform(const PxVec4& other) const + { + return column0 * other.x + column1 * other.y + column2 * other.z + column3 * other.w; + } + + //! Transform vector by matrix, equal to v' = M*v + PX_CUDA_CALLABLE PX_INLINE const PxVec3 transform(const PxVec3& other) const + { + return transform(PxVec4(other, 1.0f)).getXYZ(); + } + + //! Rotate vector by matrix, equal to v' = M*v + PX_CUDA_CALLABLE PX_INLINE const PxVec4 rotate(const PxVec4& other) const + { + return column0 * other.x + column1 * other.y + column2 * other.z; // + column3*0; + } + + //! Rotate vector by matrix, equal to v' = M*v + PX_CUDA_CALLABLE PX_INLINE const PxVec3 rotate(const PxVec3& other) const + { + return rotate(PxVec4(other, 1.0f)).getXYZ(); + } + + PX_CUDA_CALLABLE PX_INLINE const PxVec3 getBasis(int num) const + { + PX_SHARED_ASSERT(num >= 0 && num < 3); + return (&column0)[num].getXYZ(); + } + + PX_CUDA_CALLABLE PX_INLINE const PxVec3 getPosition() const + { + return column3.getXYZ(); + } + + PX_CUDA_CALLABLE PX_INLINE void setPosition(const PxVec3& position) + { + column3.x = position.x; + column3.y = position.y; + column3.z = position.z; + } + + PX_CUDA_CALLABLE PX_FORCE_INLINE const float* front() const + { + return &column0.x; + } + + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec4& operator[](unsigned int num) + { + return (&column0)[num]; + } + PX_CUDA_CALLABLE PX_FORCE_INLINE const PxVec4& operator[](unsigned int num) const + { + return (&column0)[num]; + } + + PX_CUDA_CALLABLE PX_INLINE void scale(const PxVec4& p) + { + column0 *= p.x; + column1 *= p.y; + column2 *= p.z; + column3 *= p.w; + } + + PX_CUDA_CALLABLE PX_INLINE const PxMat44 inverseRT(void) const + { + PxVec3 r0(column0.x, column1.x, column2.x), r1(column0.y, column1.y, column2.y), + r2(column0.z, column1.z, column2.z); + + return PxMat44(r0, r1, r2, -(r0 * column3.x + r1 * column3.y + r2 * column3.z)); + } + + PX_CUDA_CALLABLE PX_INLINE bool isFinite() const + { + return column0.isFinite() && column1.isFinite() && column2.isFinite() && column3.isFinite(); + } + + // Data, see above for format! + + PxVec4 column0, column1, column2, column3; // the four base vectors +}; + +// implementation from PxTransform.h +PX_CUDA_CALLABLE PX_FORCE_INLINE PxTransform::PxTransform(const PxMat44& m) +{ + PxVec3 column0 = PxVec3(m.column0.x, m.column0.y, m.column0.z); + PxVec3 column1 = PxVec3(m.column1.x, m.column1.y, m.column1.z); + PxVec3 column2 = PxVec3(m.column2.x, m.column2.y, m.column2.z); + + q = PxQuat(PxMat33(column0, column1, column2)); + p = PxVec3(m.column3.x, m.column3.y, m.column3.z); +} + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif // #ifndef PXFOUNDATION_PXMAT44_H diff --git a/sources/PhysX/PxShared/include/foundation/PxMath.h b/sources/PhysX/PxShared/include/foundation/PxMath.h new file mode 100644 index 00000000..d75d8bc3 --- /dev/null +++ b/sources/PhysX/PxShared/include/foundation/PxMath.h @@ -0,0 +1,338 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PXFOUNDATION_PXMATH_H +#define PXFOUNDATION_PXMATH_H + +/** \addtogroup foundation +@{ +*/ + +#include "foundation/PxPreprocessor.h" + +#if PX_VC +#pragma warning(push) +#pragma warning(disable : 4985) // 'symbol name': attributes not present on previous declaration +#endif +#include +#if PX_VC +#pragma warning(pop) +#endif + +#include +#include "foundation/PxIntrinsics.h" +#include "foundation/PxSharedAssert.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +// constants +static const float PxPi = float(3.141592653589793); +static const float PxHalfPi = float(1.57079632679489661923); +static const float PxTwoPi = float(6.28318530717958647692); +static const float PxInvPi = float(0.31830988618379067154); +static const float PxInvTwoPi = float(0.15915494309189533577); +static const float PxPiDivTwo = float(1.57079632679489661923); +static const float PxPiDivFour = float(0.78539816339744830962); + +/** +\brief The return value is the greater of the two specified values. +*/ +template +PX_CUDA_CALLABLE PX_FORCE_INLINE T PxMax(T a, T b) +{ + return a < b ? b : a; +} + +//! overload for float to use fsel on xbox +template <> +PX_CUDA_CALLABLE PX_FORCE_INLINE float PxMax(float a, float b) +{ + return intrinsics::selectMax(a, b); +} + +/** +\brief The return value is the lesser of the two specified values. +*/ +template +PX_CUDA_CALLABLE PX_FORCE_INLINE T PxMin(T a, T b) +{ + return a < b ? a : b; +} + +template <> +//! overload for float to use fsel on xbox +PX_CUDA_CALLABLE PX_FORCE_INLINE float PxMin(float a, float b) +{ + return intrinsics::selectMin(a, b); +} + +/* +Many of these are just implemented as PX_CUDA_CALLABLE PX_FORCE_INLINE calls to the C lib right now, +but later we could replace some of them with some approximations or more +clever stuff. +*/ + +/** +\brief abs returns the absolute value of its argument. +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE float PxAbs(float a) +{ + return intrinsics::abs(a); +} + +PX_CUDA_CALLABLE PX_FORCE_INLINE bool PxEquals(float a, float b, float eps) +{ + return (PxAbs(a - b) < eps); +} + +/** +\brief abs returns the absolute value of its argument. +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE double PxAbs(double a) +{ + return ::fabs(a); +} + +/** +\brief abs returns the absolute value of its argument. +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE int32_t PxAbs(int32_t a) +{ + return ::abs(a); +} + +/** +\brief Clamps v to the range [hi,lo] +*/ +template +PX_CUDA_CALLABLE PX_FORCE_INLINE T PxClamp(T v, T lo, T hi) +{ + PX_SHARED_ASSERT(lo <= hi); + return PxMin(hi, PxMax(lo, v)); +} + +//! \brief Square root. +PX_CUDA_CALLABLE PX_FORCE_INLINE float PxSqrt(float a) +{ + return intrinsics::sqrt(a); +} + +//! \brief Square root. +PX_CUDA_CALLABLE PX_FORCE_INLINE double PxSqrt(double a) +{ + return ::sqrt(a); +} + +//! \brief reciprocal square root. +PX_CUDA_CALLABLE PX_FORCE_INLINE float PxRecipSqrt(float a) +{ + return intrinsics::recipSqrt(a); +} + +//! \brief reciprocal square root. +PX_CUDA_CALLABLE PX_FORCE_INLINE double PxRecipSqrt(double a) +{ + return 1 / ::sqrt(a); +} + +//! trigonometry -- all angles are in radians. + +//! \brief Sine of an angle ( Unit: Radians ) +PX_CUDA_CALLABLE PX_FORCE_INLINE float PxSin(float a) +{ + return intrinsics::sin(a); +} + +//! \brief Sine of an angle ( Unit: Radians ) +PX_CUDA_CALLABLE PX_FORCE_INLINE double PxSin(double a) +{ + return ::sin(a); +} + +//! \brief Cosine of an angle (Unit: Radians) +PX_CUDA_CALLABLE PX_FORCE_INLINE float PxCos(float a) +{ + return intrinsics::cos(a); +} + +//! \brief Cosine of an angle (Unit: Radians) +PX_CUDA_CALLABLE PX_FORCE_INLINE double PxCos(double a) +{ + return ::cos(a); +} + +/** +\brief Tangent of an angle. +Unit: Radians +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE float PxTan(float a) +{ + return ::tanf(a); +} + +/** +\brief Tangent of an angle. +Unit: Radians +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE double PxTan(double a) +{ + return ::tan(a); +} + +/** +\brief Arcsine. +Returns angle between -PI/2 and PI/2 in radians +Unit: Radians +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE float PxAsin(float f) +{ + return ::asinf(PxClamp(f, -1.0f, 1.0f)); +} + +/** +\brief Arcsine. +Returns angle between -PI/2 and PI/2 in radians +Unit: Radians +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE double PxAsin(double f) +{ + return ::asin(PxClamp(f, -1.0, 1.0)); +} + +/** +\brief Arccosine. +Returns angle between 0 and PI in radians +Unit: Radians +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE float PxAcos(float f) +{ + return ::acosf(PxClamp(f, -1.0f, 1.0f)); +} + +/** +\brief Arccosine. +Returns angle between 0 and PI in radians +Unit: Radians +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE double PxAcos(double f) +{ + return ::acos(PxClamp(f, -1.0, 1.0)); +} + +/** +\brief ArcTangent. +Returns angle between -PI/2 and PI/2 in radians +Unit: Radians +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE float PxAtan(float a) +{ + return ::atanf(a); +} + +/** +\brief ArcTangent. +Returns angle between -PI/2 and PI/2 in radians +Unit: Radians +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE double PxAtan(double a) +{ + return ::atan(a); +} + +/** +\brief Arctangent of (x/y) with correct sign. +Returns angle between -PI and PI in radians +Unit: Radians +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE float PxAtan2(float x, float y) +{ + return ::atan2f(x, y); +} + +/** +\brief Arctangent of (x/y) with correct sign. +Returns angle between -PI and PI in radians +Unit: Radians +*/ +PX_CUDA_CALLABLE PX_FORCE_INLINE double PxAtan2(double x, double y) +{ + return ::atan2(x, y); +} + +//! \brief returns true if the passed number is a finite floating point number as opposed to INF, NAN, etc. +PX_CUDA_CALLABLE PX_FORCE_INLINE bool PxIsFinite(float f) +{ + return intrinsics::isFinite(f); +} + +//! \brief returns true if the passed number is a finite floating point number as opposed to INF, NAN, etc. +PX_CUDA_CALLABLE PX_FORCE_INLINE bool PxIsFinite(double f) +{ + return intrinsics::isFinite(f); +} + +PX_CUDA_CALLABLE PX_FORCE_INLINE float PxFloor(float a) +{ + return ::floorf(a); +} + +PX_CUDA_CALLABLE PX_FORCE_INLINE float PxExp(float a) +{ + return ::expf(a); +} + +PX_CUDA_CALLABLE PX_FORCE_INLINE float PxCeil(float a) +{ + return ::ceilf(a); +} + +PX_CUDA_CALLABLE PX_FORCE_INLINE float PxSign(float a) +{ + return physx::intrinsics::sign(a); +} + +PX_CUDA_CALLABLE PX_FORCE_INLINE float PxPow(float x, float y) +{ + return ::powf(x, y); +} + +PX_CUDA_CALLABLE PX_FORCE_INLINE float PxLog(float x) +{ + return ::logf(x); +} + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif // #ifndef PXFOUNDATION_PXMATH_H diff --git a/sources/PhysX/PxShared/include/foundation/PxMemory.h b/sources/PhysX/PxShared/include/foundation/PxMemory.h new file mode 100644 index 00000000..911b0d48 --- /dev/null +++ b/sources/PhysX/PxShared/include/foundation/PxMemory.h @@ -0,0 +1,110 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PXFOUNDATION_PXMEMORY_H +#define PXFOUNDATION_PXMEMORY_H + +/** \addtogroup foundation +@{ +*/ + +#include "foundation/Px.h" +#include "foundation/PxIntrinsics.h" +#include "foundation/PxSimpleTypes.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief Sets the bytes of the provided buffer to zero. + +\param dest Pointer to block of memory to set zero. +\param count Number of bytes to set to zero. + +\return Pointer to memory block (same as input) +*/ +PX_FORCE_INLINE void* PxMemZero(void* dest, PxU32 count) +{ + return physx::intrinsics::memZero(dest, count); +} + +/** +\brief Sets the bytes of the provided buffer to the specified value. + +\param dest Pointer to block of memory to set to the specified value. +\param c Value to set the bytes of the block of memory to. +\param count Number of bytes to set to the specified value. + +\return Pointer to memory block (same as input) +*/ +PX_FORCE_INLINE void* PxMemSet(void* dest, PxI32 c, PxU32 count) +{ + return physx::intrinsics::memSet(dest, c, count); +} + +/** +\brief Copies the bytes of one memory block to another. The memory blocks must not overlap. + +\note Use #PxMemMove if memory blocks overlap. + +\param dest Pointer to block of memory to copy to. +\param src Pointer to block of memory to copy from. +\param count Number of bytes to copy. + +\return Pointer to destination memory block +*/ +PX_FORCE_INLINE void* PxMemCopy(void* dest, const void* src, PxU32 count) +{ + return physx::intrinsics::memCopy(dest, src, count); +} + +/** +\brief Copies the bytes of one memory block to another. The memory blocks can overlap. + +\note Use #PxMemCopy if memory blocks do not overlap. + +\param dest Pointer to block of memory to copy to. +\param src Pointer to block of memory to copy from. +\param count Number of bytes to copy. + +\return Pointer to destination memory block +*/ +PX_FORCE_INLINE void* PxMemMove(void* dest, const void* src, PxU32 count) +{ + return physx::intrinsics::memMove(dest, src, count); +} + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif // PXFOUNDATION_PXMEMORY_H diff --git a/sources/PhysX/PxShared/include/foundation/PxPlane.h b/sources/PhysX/PxShared/include/foundation/PxPlane.h new file mode 100644 index 00000000..76f63f2c --- /dev/null +++ b/sources/PhysX/PxShared/include/foundation/PxPlane.h @@ -0,0 +1,145 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PXFOUNDATION_PXPLANE_H +#define PXFOUNDATION_PXPLANE_H + +/** \addtogroup foundation +@{ +*/ + +#include "foundation/PxMath.h" +#include "foundation/PxVec3.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief Representation of a plane. + + Plane equation used: n.dot(v) + d = 0 +*/ +class PxPlane +{ + public: + /** + \brief Constructor + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxPlane() + { + } + + /** + \brief Constructor from a normal and a distance + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxPlane(float nx, float ny, float nz, float distance) : n(nx, ny, nz), d(distance) + { + } + + /** + \brief Constructor from a normal and a distance + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxPlane(const PxVec3& normal, float distance) : n(normal), d(distance) + { + } + + /** + \brief Constructor from a point on the plane and a normal + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxPlane(const PxVec3& point, const PxVec3& normal) + : n(normal), d(-point.dot(n)) // p satisfies normal.dot(p) + d = 0 + { + } + + /** + \brief Constructor from three points + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxPlane(const PxVec3& p0, const PxVec3& p1, const PxVec3& p2) + { + n = (p1 - p0).cross(p2 - p0).getNormalized(); + d = -p0.dot(n); + } + + /** + \brief returns true if the two planes are exactly equal + */ + PX_CUDA_CALLABLE PX_INLINE bool operator==(const PxPlane& p) const + { + return n == p.n && d == p.d; + } + + PX_CUDA_CALLABLE PX_FORCE_INLINE float distance(const PxVec3& p) const + { + return p.dot(n) + d; + } + + PX_CUDA_CALLABLE PX_FORCE_INLINE bool contains(const PxVec3& p) const + { + return PxAbs(distance(p)) < (1.0e-7f); + } + + /** + \brief projects p into the plane + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 project(const PxVec3& p) const + { + return p - n * distance(p); + } + + /** + \brief find an arbitrary point in the plane + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 pointInPlane() const + { + return -n * d; + } + + /** + \brief equivalent plane with unit normal + */ + + PX_CUDA_CALLABLE PX_FORCE_INLINE void normalize() + { + float denom = 1.0f / n.magnitude(); + n *= denom; + d *= denom; + } + + PxVec3 n; //!< The normal to the plane + float d; //!< The distance from the origin +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif // #ifndef PXFOUNDATION_PXPLANE_H diff --git a/sources/PhysX/PxShared/include/foundation/PxPreprocessor.h b/sources/PhysX/PxShared/include/foundation/PxPreprocessor.h new file mode 100644 index 00000000..bdd6cc7b --- /dev/null +++ b/sources/PhysX/PxShared/include/foundation/PxPreprocessor.h @@ -0,0 +1,535 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PXFOUNDATION_PXPREPROCESSOR_H +#define PXFOUNDATION_PXPREPROCESSOR_H + +#include +#if !defined(PX_GENERATE_META_DATA) +#include +#endif +/** \addtogroup foundation + @{ +*/ + +#define PX_STRINGIZE_HELPER(X) #X +#define PX_STRINGIZE(X) PX_STRINGIZE_HELPER(X) + +#define PX_CONCAT_HELPER(X, Y) X##Y +#define PX_CONCAT(X, Y) PX_CONCAT_HELPER(X, Y) + +/* +The following preprocessor identifiers specify compiler, OS, and architecture. +All definitions have a value of 1 or 0, use '#if' instead of '#ifdef'. +*/ + +/** +Compiler defines, see http://sourceforge.net/p/predef/wiki/Compilers/ +*/ +#if defined(_MSC_VER) +#if _MSC_VER >= 1910 +#define PX_VC 15 +#elif _MSC_VER >= 1900 +#define PX_VC 14 +#elif _MSC_VER >= 1800 +#define PX_VC 12 +#elif _MSC_VER >= 1700 +#define PX_VC 11 +#elif _MSC_VER >= 1600 +#define PX_VC 10 +#elif _MSC_VER >= 1500 +#define PX_VC 9 +#else +#error "Unknown VC version" +#endif +#elif defined(__clang__) +#define PX_CLANG 1 + #if defined (__clang_major__) + #define PX_CLANG_MAJOR __clang_major__ + #elif defined (_clang_major) + #define PX_CLANG_MAJOR _clang_major + #else + #define PX_CLANG_MAJOR 0 + #endif +#elif defined(__GNUC__) // note: __clang__ implies __GNUC__ +#define PX_GCC 1 +#else +#error "Unknown compiler" +#endif + +/** +Operating system defines, see http://sourceforge.net/p/predef/wiki/OperatingSystems/ +*/ +#if defined(_XBOX_ONE) +#define PX_XBOXONE 1 +#elif defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_APP +#define PX_UWP 1 +#elif defined(_WIN64) // note: _XBOX_ONE implies _WIN64 +#define PX_WIN64 1 +#elif defined(_WIN32) // note: _M_PPC implies _WIN32 +#define PX_WIN32 1 +#elif defined(__ANDROID__) +#define PX_ANDROID 1 +#elif defined(__linux__) || defined (__EMSCRIPTEN__) // note: __ANDROID__ implies __linux__ +#define PX_LINUX 1 +#elif defined(__APPLE__) && (defined(__arm__) || defined(__arm64__)) +#define PX_IOS 1 +#elif defined(__APPLE__) +#define PX_OSX 1 +#elif defined(__ORBIS__) +#define PX_PS4 1 +#elif defined(__NX__) +#define PX_SWITCH 1 +#else +#error "Unknown operating system" +#endif + +/** +Architecture defines, see http://sourceforge.net/p/predef/wiki/Architectures/ +*/ +#if defined(__x86_64__) || defined(_M_X64) // ps4 compiler defines _M_X64 without value +#define PX_X64 1 +#elif defined(__i386__) || defined(_M_IX86) || defined (__EMSCRIPTEN__) +#define PX_X86 1 +#elif defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) +#define PX_A64 1 +#elif defined(__arm__) || defined(_M_ARM) +#define PX_ARM 1 +#elif defined(__ppc__) || defined(_M_PPC) || defined(__CELLOS_LV2__) +#define PX_PPC 1 +#else +#error "Unknown architecture" +#endif + +/** +SIMD defines +*/ +#if !defined(PX_SIMD_DISABLED) +#if defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64) || (defined (__EMSCRIPTEN__) && defined(__SSE2__)) +#define PX_SSE2 1 +#endif +#if defined(_M_ARM) || defined(__ARM_NEON__) || defined(__ARM_NEON) +#define PX_NEON 1 +#endif +#if defined(_M_PPC) || defined(__CELLOS_LV2__) +#define PX_VMX 1 +#endif +#endif + +/** +define anything not defined on this platform to 0 +*/ +#ifndef PX_VC +#define PX_VC 0 +#endif +#ifndef PX_CLANG +#define PX_CLANG 0 +#endif +#ifndef PX_GCC +#define PX_GCC 0 +#endif +#ifndef PX_XBOXONE +#define PX_XBOXONE 0 +#endif +#ifndef PX_WIN64 +#define PX_WIN64 0 +#endif +#ifndef PX_WIN32 +#define PX_WIN32 0 +#endif +#ifndef PX_ANDROID +#define PX_ANDROID 0 +#endif +#ifndef PX_LINUX +#define PX_LINUX 0 +#endif +#ifndef PX_IOS +#define PX_IOS 0 +#endif +#ifndef PX_OSX +#define PX_OSX 0 +#endif +#ifndef PX_PS4 +#define PX_PS4 0 +#endif +#ifndef PX_SWITCH +#define PX_SWITCH 0 +#endif +#ifndef PX_UWP +#define PX_UWP 0 +#endif +#ifndef PX_X64 +#define PX_X64 0 +#endif +#ifndef PX_X86 +#define PX_X86 0 +#endif +#ifndef PX_A64 +#define PX_A64 0 +#endif +#ifndef PX_ARM +#define PX_ARM 0 +#endif +#ifndef PX_PPC +#define PX_PPC 0 +#endif +#ifndef PX_SSE2 +#define PX_SSE2 0 +#endif +#ifndef PX_NEON +#define PX_NEON 0 +#endif +#ifndef PX_VMX +#define PX_VMX 0 +#endif + +/* +define anything not defined through the command line to 0 +*/ +#ifndef PX_DEBUG +#define PX_DEBUG 0 +#endif +#ifndef PX_CHECKED +#define PX_CHECKED 0 +#endif +#ifndef PX_PROFILE +#define PX_PROFILE 0 +#endif +#ifndef PX_DEBUG_CRT +#define PX_DEBUG_CRT 0 +#endif +#ifndef PX_NVTX +#define PX_NVTX 0 +#endif +#ifndef PX_DOXYGEN +#define PX_DOXYGEN 0 +#endif + +/** +family shortcuts +*/ +// compiler +#define PX_GCC_FAMILY (PX_CLANG || PX_GCC) +// os +#define PX_WINDOWS_FAMILY (PX_WIN32 || PX_WIN64 || PX_UWP) +#define PX_MICROSOFT_FAMILY (PX_XBOXONE || PX_WINDOWS_FAMILY) +#define PX_LINUX_FAMILY (PX_LINUX || PX_ANDROID) +#define PX_APPLE_FAMILY (PX_IOS || PX_OSX) // equivalent to #if __APPLE__ +#define PX_UNIX_FAMILY (PX_LINUX_FAMILY || PX_APPLE_FAMILY) // shortcut for unix/posix platforms +#if defined(__EMSCRIPTEN__) +#define PX_EMSCRIPTEN 1 +#else +#define PX_EMSCRIPTEN 0 +#endif +// architecture +#define PX_INTEL_FAMILY (PX_X64 || PX_X86) +#define PX_ARM_FAMILY (PX_ARM || PX_A64) +#define PX_P64_FAMILY (PX_X64 || PX_A64) // shortcut for 64-bit architectures + +/** +C++ standard library defines +*/ +#if defined(_LIBCPP_VERSION) || PX_WIN64 || PX_WIN32 || PX_PS4 || PX_XBOXONE || PX_UWP || PX_EMSCRIPTEN +#define PX_LIBCPP 1 +#else +#define PX_LIBCPP 0 +#endif + +// legacy define for PhysX +#define PX_WINDOWS (PX_WINDOWS_FAMILY && !PX_ARM_FAMILY) + +/** +Assert macro +*/ +#ifndef PX_ENABLE_ASSERTS +#if PX_DEBUG && !defined(__CUDACC__) +#define PX_ENABLE_ASSERTS 1 +#else +#define PX_ENABLE_ASSERTS 0 +#endif +#endif + +/** +DLL export macros +*/ +#ifndef PX_C_EXPORT +#if PX_WINDOWS_FAMILY || PX_LINUX +#define PX_C_EXPORT extern "C" +#else +#define PX_C_EXPORT +#endif +#endif + +#if PX_UNIX_FAMILY&& __GNUC__ >= 4 +#define PX_UNIX_EXPORT __attribute__((visibility("default"))) +#else +#define PX_UNIX_EXPORT +#endif + +#if (PX_WINDOWS_FAMILY || PX_XBOXONE || PX_PS4) +#define PX_DLL_EXPORT __declspec(dllexport) +#define PX_DLL_IMPORT __declspec(dllimport) +#else +#define PX_DLL_EXPORT PX_UNIX_EXPORT +#define PX_DLL_IMPORT +#endif + +/** +Calling convention +*/ +#ifndef PX_CALL_CONV +#if PX_MICROSOFT_FAMILY +#define PX_CALL_CONV __cdecl +#else +#define PX_CALL_CONV +#endif +#endif + +/** +Pack macros - disabled on SPU because they are not supported +*/ +#if PX_VC +#define PX_PUSH_PACK_DEFAULT __pragma(pack(push, 8)) +#define PX_POP_PACK __pragma(pack(pop)) +#elif PX_GCC_FAMILY +#define PX_PUSH_PACK_DEFAULT _Pragma("pack(push, 8)") +#define PX_POP_PACK _Pragma("pack(pop)") +#else +#define PX_PUSH_PACK_DEFAULT +#define PX_POP_PACK +#endif + +/** +Inline macro +*/ +#define PX_INLINE inline +#if PX_MICROSOFT_FAMILY +#pragma inline_depth(255) +#endif + +/** +Force inline macro +*/ +#if PX_VC +#define PX_FORCE_INLINE __forceinline +#elif PX_LINUX // Workaround; Fedora Core 3 do not agree with force inline and PxcPool +#define PX_FORCE_INLINE inline +#elif PX_GCC_FAMILY +#define PX_FORCE_INLINE inline __attribute__((always_inline)) +#else +#define PX_FORCE_INLINE inline +#endif + +/** +Noinline macro +*/ +#if PX_MICROSOFT_FAMILY +#define PX_NOINLINE __declspec(noinline) +#elif PX_GCC_FAMILY +#define PX_NOINLINE __attribute__((noinline)) +#else +#define PX_NOINLINE +#endif + +/** +Restrict macro +*/ +#if defined(__CUDACC__) +#define PX_RESTRICT __restrict__ +#else +#define PX_RESTRICT __restrict +#endif + +/** +Noalias macro +*/ +#if PX_MICROSOFT_FAMILY +#define PX_NOALIAS __declspec(noalias) +#else +#define PX_NOALIAS +#endif + +/** +Alignment macros + +PX_ALIGN_PREFIX and PX_ALIGN_SUFFIX can be used for type alignment instead of aligning individual variables as follows: +PX_ALIGN_PREFIX(16) +struct A { +... +} PX_ALIGN_SUFFIX(16); +This declaration style is parsed correctly by Visual Assist. + +*/ +#ifndef PX_ALIGN +#if PX_MICROSOFT_FAMILY +#define PX_ALIGN(alignment, decl) __declspec(align(alignment)) decl +#define PX_ALIGN_PREFIX(alignment) __declspec(align(alignment)) +#define PX_ALIGN_SUFFIX(alignment) +#elif PX_GCC_FAMILY +#define PX_ALIGN(alignment, decl) decl __attribute__((aligned(alignment))) +#define PX_ALIGN_PREFIX(alignment) +#define PX_ALIGN_SUFFIX(alignment) __attribute__((aligned(alignment))) +#elif defined __CUDACC__ +#define PX_ALIGN(alignment, decl) __align__(alignment) decl +#define PX_ALIGN_PREFIX(alignment) +#define PX_ALIGN_SUFFIX(alignment) __align__(alignment)) +#else +#define PX_ALIGN(alignment, decl) +#define PX_ALIGN_PREFIX(alignment) +#define PX_ALIGN_SUFFIX(alignment) +#endif +#endif + +/** +Deprecated macro +- To deprecate a function: Place PX_DEPRECATED at the start of the function header (leftmost word). +- To deprecate a 'typedef', a 'struct' or a 'class': Place PX_DEPRECATED directly after the keywords ('typdef', +'struct', 'class'). + +Use these macro definitions to create warnings for deprecated functions +\#define PX_DEPRECATED __declspec(deprecated) // Microsoft +\#define PX_DEPRECATED __attribute__((deprecated())) // GCC +*/ +#define PX_DEPRECATED + +/** +General defines +*/ + +// static assert +#if(defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))) || (PX_PS4) || (PX_APPLE_FAMILY) || (PX_SWITCH) || (PX_CLANG && PX_ARM) +#define PX_COMPILE_TIME_ASSERT(exp) typedef char PX_CONCAT(PxCompileTimeAssert_Dummy, __COUNTER__)[(exp) ? 1 : -1] __attribute__((unused)) +#else +#define PX_COMPILE_TIME_ASSERT(exp) typedef char PxCompileTimeAssert_Dummy[(exp) ? 1 : -1] +#endif + +#if PX_GCC_FAMILY +#define PX_OFFSET_OF(X, Y) __builtin_offsetof(X, Y) +#else +#define PX_OFFSET_OF(X, Y) offsetof(X, Y) +#endif + +#define PX_OFFSETOF_BASE 0x100 // casting the null ptr takes a special-case code path, which we don't want +#define PX_OFFSET_OF_RT(Class, Member) \ + (reinterpret_cast(&reinterpret_cast(PX_OFFSETOF_BASE)->Member) - size_t(PX_OFFSETOF_BASE)) + +// check that exactly one of NDEBUG and _DEBUG is defined +#if !defined(NDEBUG) ^ defined(_DEBUG) +#error Exactly one of NDEBUG and _DEBUG needs to be defined! +#endif + +// make sure PX_CHECKED is defined in all _DEBUG configurations as well +#if !PX_CHECKED && PX_DEBUG +#error PX_CHECKED must be defined when PX_DEBUG is defined +#endif + +#ifdef __CUDACC__ +#define PX_CUDA_CALLABLE __host__ __device__ +#else +#define PX_CUDA_CALLABLE +#endif + +// avoid unreferenced parameter warning +// preferred solution: omit the parameter's name from the declaration +template +PX_CUDA_CALLABLE PX_INLINE void PX_UNUSED(T const&) +{ +} + +// Ensure that the application hasn't tweaked the pack value to less than 8, which would break +// matching between the API headers and the binaries +// This assert works on win32/win64, but may need further specialization on other platforms. +// Some GCC compilers need the compiler flag -malign-double to be set. +// Apparently the apple-clang-llvm compiler doesn't support malign-double. +#if PX_PS4 || PX_APPLE_FAMILY || (PX_CLANG && !PX_ARM) +struct PxPackValidation +{ + char _; + long a; +}; +#elif PX_ANDROID || (PX_CLANG && PX_ARM) +struct PxPackValidation +{ + char _; + double a; +}; +#else +struct PxPackValidation +{ + char _; + long long a; +}; +#endif +// clang (as of version 3.9) cannot align doubles on 8 byte boundary when compiling for Intel 32 bit target +#if !PX_APPLE_FAMILY && !PX_EMSCRIPTEN && !(PX_CLANG && PX_X86) +PX_COMPILE_TIME_ASSERT(PX_OFFSET_OF(PxPackValidation, a) == 8); +#endif + +// use in a cpp file to suppress LNK4221 +#if PX_VC +#define PX_DUMMY_SYMBOL \ + namespace \ + { \ + char PxDummySymbol; \ + } +#else +#define PX_DUMMY_SYMBOL +#endif + +#if PX_GCC_FAMILY +#define PX_WEAK_SYMBOL __attribute__((weak)) // this is to support SIMD constant merging in template specialization +#else +#define PX_WEAK_SYMBOL +#endif + +// Macro for avoiding default assignment and copy, because doing this by inheritance can increase class size on some +// platforms. +#define PX_NOCOPY(Class) \ + \ +protected: \ + Class(const Class&); \ + Class& operator=(const Class&); + +#ifndef DISABLE_CUDA_PHYSX +//CUDA is currently supported only on windows +#define PX_SUPPORT_GPU_PHYSX ((PX_WINDOWS_FAMILY) || (PX_LINUX && PX_X64)) +#else +#define PX_SUPPORT_GPU_PHYSX 0 +#endif + +#define PX_SUPPORT_COMPUTE_PHYSX 0 + +#ifndef PX_SUPPORT_EXTERN_TEMPLATE +#define PX_SUPPORT_EXTERN_TEMPLATE ((!PX_ANDROID) && (PX_VC != 11)) +#else +#define PX_SUPPORT_EXTERN_TEMPLATE 0 +#endif + +/** @} */ +#endif // #ifndef PXFOUNDATION_PXPREPROCESSOR_H diff --git a/sources/PhysX/PxShared/include/foundation/PxProfiler.h b/sources/PhysX/PxShared/include/foundation/PxProfiler.h new file mode 100644 index 00000000..a949b723 --- /dev/null +++ b/sources/PhysX/PxShared/include/foundation/PxProfiler.h @@ -0,0 +1,99 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. + +#ifndef PXFOUNDATION_PXPROFILER_H +#define PXFOUNDATION_PXPROFILER_H + +#include "foundation/Px.h" + +namespace physx +{ + +/** +\brief The pure virtual callback interface for general purpose instrumentation and profiling of GameWorks modules as +well as applications +*/ +class PxProfilerCallback +{ +protected: + virtual ~PxProfilerCallback() {} + +public: + /************************************************************************************************************************** + Instrumented profiling events + ***************************************************************************************************************************/ + + /** + \brief Mark the beginning of a nested profile block + \param[in] eventName Event name. Must be a persistent const char * + \param[in] detached True for cross thread events + \param[in] contextId the context id of this zone. Zones with the same id belong to the same group. 0 is used for no specific group. + \return Returns implementation-specific profiler data for this event + */ + virtual void* zoneStart(const char* eventName, bool detached, uint64_t contextId) = 0; + + /** + \brief Mark the end of a nested profile block + \param[in] profilerData The data returned by the corresponding zoneStart call (or NULL if not available) + \param[in] eventName The name of the zone ending, must match the corresponding name passed with 'zoneStart'. Must be a persistent const char *. + \param[in] detached True for cross thread events. Should match the value passed to zoneStart. + \param[in] contextId The context of this zone. Should match the value passed to zoneStart. + + \note eventName plus contextId can be used to uniquely match up start and end of a zone. + */ + virtual void zoneEnd(void* profilerData, const char* eventName, bool detached, uint64_t contextId) = 0; +}; + +class PxProfileScoped +{ + public: + PX_FORCE_INLINE PxProfileScoped(PxProfilerCallback* callback, const char* eventName, bool detached, uint64_t contextId) : mCallback(callback), mProfilerData(NULL) + { + if(mCallback) + { + mEventName = eventName; + mContextId = contextId; + mDetached = detached; + mProfilerData = mCallback->zoneStart(eventName, detached, contextId); + } + } + + PX_FORCE_INLINE ~PxProfileScoped() + { + if(mCallback) + mCallback->zoneEnd(mProfilerData, mEventName, mDetached, mContextId); + } + PxProfilerCallback* mCallback; + const char* mEventName; + void* mProfilerData; + uint64_t mContextId; + bool mDetached; +}; + +} // end of physx namespace + +#endif // PXFOUNDATION_PXPROFILER_H diff --git a/sources/PhysX/PxShared/include/foundation/PxQuat.h b/sources/PhysX/PxShared/include/foundation/PxQuat.h new file mode 100644 index 00000000..f29a3727 --- /dev/null +++ b/sources/PhysX/PxShared/include/foundation/PxQuat.h @@ -0,0 +1,403 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PXFOUNDATION_PXQUAT_H +#define PXFOUNDATION_PXQUAT_H + +/** \addtogroup foundation +@{ +*/ + +#include "foundation/PxVec3.h" +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief This is a quaternion class. For more information on quaternion mathematics +consult a mathematics source on complex numbers. + +*/ + +class PxQuat +{ + public: + /** + \brief Default constructor, does not do any initialization. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxQuat() + { + } + + //! identity constructor + PX_CUDA_CALLABLE PX_INLINE PxQuat(PxIDENTITY r) : x(0.0f), y(0.0f), z(0.0f), w(1.0f) + { + PX_UNUSED(r); + } + + /** + \brief Constructor from a scalar: sets the real part w to the scalar value, and the imaginary parts (x,y,z) to zero + */ + explicit PX_CUDA_CALLABLE PX_FORCE_INLINE PxQuat(float r) : x(0.0f), y(0.0f), z(0.0f), w(r) + { + } + + /** + \brief Constructor. Take note of the order of the elements! + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxQuat(float nx, float ny, float nz, float nw) : x(nx), y(ny), z(nz), w(nw) + { + } + + /** + \brief Creates from angle-axis representation. + + Axis must be normalized! + + Angle is in radians! + + Unit: Radians + */ + PX_CUDA_CALLABLE PX_INLINE PxQuat(float angleRadians, const PxVec3& unitAxis) + { + PX_SHARED_ASSERT(PxAbs(1.0f - unitAxis.magnitude()) < 1e-3f); + const float a = angleRadians * 0.5f; + const float s = PxSin(a); + w = PxCos(a); + x = unitAxis.x * s; + y = unitAxis.y * s; + z = unitAxis.z * s; + } + + /** + \brief Copy ctor. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxQuat(const PxQuat& v) : x(v.x), y(v.y), z(v.z), w(v.w) + { + } + + /** + \brief Creates from orientation matrix. + + \param[in] m Rotation matrix to extract quaternion from. + */ + PX_CUDA_CALLABLE PX_INLINE explicit PxQuat(const PxMat33& m); /* defined in PxMat33.h */ + + /** + \brief returns true if quat is identity + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE bool isIdentity() const + { + return x==0.0f && y==0.0f && z==0.0f && w==1.0f; + } + + /** + \brief returns true if all elements are finite (not NAN or INF, etc.) + */ + PX_CUDA_CALLABLE bool isFinite() const + { + return PxIsFinite(x) && PxIsFinite(y) && PxIsFinite(z) && PxIsFinite(w); + } + + /** + \brief returns true if finite and magnitude is close to unit + */ + PX_CUDA_CALLABLE bool isUnit() const + { + const float unitTolerance = 1e-4f; + return isFinite() && PxAbs(magnitude() - 1) < unitTolerance; + } + + /** + \brief returns true if finite and magnitude is reasonably close to unit to allow for some accumulation of error vs + isValid + */ + PX_CUDA_CALLABLE bool isSane() const + { + const float unitTolerance = 1e-2f; + return isFinite() && PxAbs(magnitude() - 1) < unitTolerance; + } + + /** + \brief returns true if the two quaternions are exactly equal + */ + PX_CUDA_CALLABLE PX_INLINE bool operator==(const PxQuat& q) const + { + return x == q.x && y == q.y && z == q.z && w == q.w; + } + + /** + \brief converts this quaternion to angle-axis representation + */ + PX_CUDA_CALLABLE PX_INLINE void toRadiansAndUnitAxis(float& angle, PxVec3& axis) const + { + const float quatEpsilon = 1.0e-8f; + const float s2 = x * x + y * y + z * z; + if(s2 < quatEpsilon * quatEpsilon) // can't extract a sensible axis + { + angle = 0.0f; + axis = PxVec3(1.0f, 0.0f, 0.0f); + } + else + { + const float s = PxRecipSqrt(s2); + axis = PxVec3(x, y, z) * s; + angle = PxAbs(w) < quatEpsilon ? PxPi : PxAtan2(s2 * s, w) * 2.0f; + } + } + + /** + \brief Gets the angle between this quat and the identity quaternion. + + Unit: Radians + */ + PX_CUDA_CALLABLE PX_INLINE float getAngle() const + { + return PxAcos(w) * 2.0f; + } + + /** + \brief Gets the angle between this quat and the argument + + Unit: Radians + */ + PX_CUDA_CALLABLE PX_INLINE float getAngle(const PxQuat& q) const + { + return PxAcos(dot(q)) * 2.0f; + } + + /** + \brief This is the squared 4D vector length, should be 1 for unit quaternions. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE float magnitudeSquared() const + { + return x * x + y * y + z * z + w * w; + } + + /** + \brief returns the scalar product of this and other. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE float dot(const PxQuat& v) const + { + return x * v.x + y * v.y + z * v.z + w * v.w; + } + + PX_CUDA_CALLABLE PX_INLINE PxQuat getNormalized() const + { + const float s = 1.0f / magnitude(); + return PxQuat(x * s, y * s, z * s, w * s); + } + + PX_CUDA_CALLABLE PX_INLINE float magnitude() const + { + return PxSqrt(magnitudeSquared()); + } + + // modifiers: + /** + \brief maps to the closest unit quaternion. + */ + PX_CUDA_CALLABLE PX_INLINE float normalize() // convert this PxQuat to a unit quaternion + { + const float mag = magnitude(); + if(mag != 0.0f) + { + const float imag = 1.0f / mag; + + x *= imag; + y *= imag; + z *= imag; + w *= imag; + } + return mag; + } + + /* + \brief returns the conjugate. + + \note for unit quaternions, this is the inverse. + */ + PX_CUDA_CALLABLE PX_INLINE PxQuat getConjugate() const + { + return PxQuat(-x, -y, -z, w); + } + + /* + \brief returns imaginary part. + */ + PX_CUDA_CALLABLE PX_INLINE PxVec3 getImaginaryPart() const + { + return PxVec3(x, y, z); + } + + /** brief computes rotation of x-axis */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 getBasisVector0() const + { + const float x2 = x * 2.0f; + const float w2 = w * 2.0f; + return PxVec3((w * w2) - 1.0f + x * x2, (z * w2) + y * x2, (-y * w2) + z * x2); + } + + /** brief computes rotation of y-axis */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 getBasisVector1() const + { + const float y2 = y * 2.0f; + const float w2 = w * 2.0f; + return PxVec3((-z * w2) + x * y2, (w * w2) - 1.0f + y * y2, (x * w2) + z * y2); + } + + /** brief computes rotation of z-axis */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 getBasisVector2() const + { + const float z2 = z * 2.0f; + const float w2 = w * 2.0f; + return PxVec3((y * w2) + x * z2, (-x * w2) + y * z2, (w * w2) - 1.0f + z * z2); + } + + /** + rotates passed vec by this (assumed unitary) + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE const PxVec3 rotate(const PxVec3& v) const + { + const float vx = 2.0f * v.x; + const float vy = 2.0f * v.y; + const float vz = 2.0f * v.z; + const float w2 = w * w - 0.5f; + const float dot2 = (x * vx + y * vy + z * vz); + return PxVec3((vx * w2 + (y * vz - z * vy) * w + x * dot2), (vy * w2 + (z * vx - x * vz) * w + y * dot2), + (vz * w2 + (x * vy - y * vx) * w + z * dot2)); + } + + /** + inverse rotates passed vec by this (assumed unitary) + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE const PxVec3 rotateInv(const PxVec3& v) const + { + const float vx = 2.0f * v.x; + const float vy = 2.0f * v.y; + const float vz = 2.0f * v.z; + const float w2 = w * w - 0.5f; + const float dot2 = (x * vx + y * vy + z * vz); + return PxVec3((vx * w2 - (y * vz - z * vy) * w + x * dot2), (vy * w2 - (z * vx - x * vz) * w + y * dot2), + (vz * w2 - (x * vy - y * vx) * w + z * dot2)); + } + + /** + \brief Assignment operator + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxQuat& operator=(const PxQuat& p) + { + x = p.x; + y = p.y; + z = p.z; + w = p.w; + return *this; + } + + PX_CUDA_CALLABLE PX_FORCE_INLINE PxQuat& operator*=(const PxQuat& q) + { + const float tx = w * q.x + q.w * x + y * q.z - q.y * z; + const float ty = w * q.y + q.w * y + z * q.x - q.z * x; + const float tz = w * q.z + q.w * z + x * q.y - q.x * y; + + w = w * q.w - q.x * x - y * q.y - q.z * z; + x = tx; + y = ty; + z = tz; + + return *this; + } + + PX_CUDA_CALLABLE PX_FORCE_INLINE PxQuat& operator+=(const PxQuat& q) + { + x += q.x; + y += q.y; + z += q.z; + w += q.w; + return *this; + } + + PX_CUDA_CALLABLE PX_FORCE_INLINE PxQuat& operator-=(const PxQuat& q) + { + x -= q.x; + y -= q.y; + z -= q.z; + w -= q.w; + return *this; + } + + PX_CUDA_CALLABLE PX_FORCE_INLINE PxQuat& operator*=(const float s) + { + x *= s; + y *= s; + z *= s; + w *= s; + return *this; + } + + /** quaternion multiplication */ + PX_CUDA_CALLABLE PX_INLINE PxQuat operator*(const PxQuat& q) const + { + return PxQuat(w * q.x + q.w * x + y * q.z - q.y * z, w * q.y + q.w * y + z * q.x - q.z * x, + w * q.z + q.w * z + x * q.y - q.x * y, w * q.w - x * q.x - y * q.y - z * q.z); + } + + /** quaternion addition */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxQuat operator+(const PxQuat& q) const + { + return PxQuat(x + q.x, y + q.y, z + q.z, w + q.w); + } + + /** quaternion subtraction */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxQuat operator-() const + { + return PxQuat(-x, -y, -z, -w); + } + + PX_CUDA_CALLABLE PX_FORCE_INLINE PxQuat operator-(const PxQuat& q) const + { + return PxQuat(x - q.x, y - q.y, z - q.z, w - q.w); + } + + PX_CUDA_CALLABLE PX_FORCE_INLINE PxQuat operator*(float r) const + { + return PxQuat(x * r, y * r, z * r, w * r); + } + + /** the quaternion elements */ + float x, y, z, w; +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif // #ifndef PXFOUNDATION_PXQUAT_H diff --git a/sources/PhysX/PxShared/include/foundation/PxSharedAssert.h b/sources/PhysX/PxShared/include/foundation/PxSharedAssert.h new file mode 100644 index 00000000..1cb05cb2 --- /dev/null +++ b/sources/PhysX/PxShared/include/foundation/PxSharedAssert.h @@ -0,0 +1,46 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PXFOUNDATION_PXASSERT_H +#define PXFOUNDATION_PXASSERT_H + +/** \addtogroup foundation +@{ */ + +#include "foundation/Px.h" + +#if !PX_ENABLE_ASSERTS + #define PX_SHARED_ASSERT(exp) ((void)0) +#else + #include + #define PX_SHARED_ASSERT(exp) assert(exp); +#endif // !PX_ENABLE_ASSERTS + +/** @} */ +#endif // #ifndef PXFOUNDATION_PXASSERT_H diff --git a/sources/PhysX/PxShared/include/foundation/PxSimpleTypes.h b/sources/PhysX/PxShared/include/foundation/PxSimpleTypes.h new file mode 100644 index 00000000..a9ced086 --- /dev/null +++ b/sources/PhysX/PxShared/include/foundation/PxSimpleTypes.h @@ -0,0 +1,112 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PXFOUNDATION_PXSIMPLETYPES_H +#define PXFOUNDATION_PXSIMPLETYPES_H + +/** \addtogroup foundation + @{ +*/ + +// Platform specific types: +// Design note: Its OK to use int for general loop variables and temps. + +#include "foundation/PxPreprocessor.h" +#if PX_VC +#pragma warning(push) +#pragma warning(disable : 4668) // suppressing warning generated by Microsoft Visual Studio when including this standard +// header +#endif + +#if PX_LINUX +#define __STDC_LIMIT_MACROS +#endif + +#include +#if PX_VC +#pragma warning(pop) +#endif + +#if PX_VC // we could use inttypes.h starting with VC12 +#define PX_PRIu64 "I64u" +#else +#if !PX_PS4 && !PX_APPLE_FAMILY +#define __STDC_FORMAT_MACROS +#endif +#include +#define PX_PRIu64 PRIu64 +#endif + +namespace physx +{ +typedef int64_t PxI64; +typedef uint64_t PxU64; +typedef int32_t PxI32; +typedef uint32_t PxU32; +typedef int16_t PxI16; +typedef uint16_t PxU16; +typedef int8_t PxI8; +typedef uint8_t PxU8; +typedef float PxF32; +typedef double PxF64; +typedef float PxReal; +} + +// Type ranges + +// These are here because we sometimes have non-IEEE compliant platforms to deal with. +// Removal is under consideration (issue GWSD-34) + +#define PX_MAX_F32 3.4028234663852885981170418348452e+38F +// maximum possible float value +#define PX_MAX_F64 DBL_MAX // maximum possible double value + +#define PX_EPS_F32 FLT_EPSILON // maximum relative error of float rounding +#define PX_EPS_F64 DBL_EPSILON // maximum relative error of double rounding + +#define PX_MAX_REAL PX_MAX_F32 +#define PX_EPS_REAL PX_EPS_F32 +#define PX_NORMALIZATION_EPSILON float(1e-20f) + +// Legacy type ranges used by PhysX +#define PX_MAX_I8 INT8_MAX +#define PX_MIN_I8 INT8_MIN +#define PX_MAX_U8 UINT8_MAX +#define PX_MIN_U8 UINT8_MIN +#define PX_MAX_I16 INT16_MAX +#define PX_MIN_I16 INT16_MIN +#define PX_MAX_U16 UINT16_MAX +#define PX_MIN_U16 UINT16_MIN +#define PX_MAX_I32 INT32_MAX +#define PX_MIN_I32 INT32_MIN +#define PX_MAX_U32 UINT32_MAX +#define PX_MIN_U32 UINT32_MIN + +/** @} */ +#endif // #ifndef PXFOUNDATION_PXSIMPLETYPES_H diff --git a/sources/PhysX/PxShared/include/foundation/PxStrideIterator.h b/sources/PhysX/PxShared/include/foundation/PxStrideIterator.h new file mode 100644 index 00000000..dd6dd10b --- /dev/null +++ b/sources/PhysX/PxShared/include/foundation/PxStrideIterator.h @@ -0,0 +1,353 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PXFOUNDATION_PXSTRIDEITERATOR_H +#define PXFOUNDATION_PXSTRIDEITERATOR_H + +#include "foundation/Px.h" +#include "foundation/PxSharedAssert.h" + +/** \addtogroup foundation + @{ +*/ + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief Iterator class for iterating over arrays of data that may be interleaved with other data. + +This class is used for iterating over arrays of elements that may have a larger element to element +offset, called the stride, than the size of the element itself (non-contiguous). + +The template parameter T denotes the type of the element accessed. The stride itself +is stored as a member field so multiple instances of a PxStrideIterator class can have +different strides. This is useful for cases were the stride depends on runtime configuration. + +The stride iterator can be used for index based access, e.g.: +\code + PxStrideIterator strideArray(...); + for (unsigned i = 0; i < 10; ++i) + { + PxVec3& vec = strideArray[i]; + ... + } +\endcode +or iteration by increment, e.g.: +\code + PxStrideIterator strideBegin(...); + PxStrideIterator strideEnd(strideBegin + 10); + for (PxStrideIterator it = strideBegin; it < strideEnd; ++it) + { + PxVec3& vec = *it; + ... + } +\endcode + +Two special cases: +- A stride of sizeof(T) represents a regular c array of type T. +- A stride of 0 can be used to describe re-occurrence of the same element multiple times. + +*/ +template +class PxStrideIterator +{ + +#if !PX_DOXYGEN + template + struct StripConst + { + typedef X Type; + }; + + template + struct StripConst + { + typedef X Type; + }; +#endif + + public: + /** + \brief Constructor. + + Optionally takes a pointer to an element and a stride. + + \param[in] ptr pointer to element, defaults to NULL. + \param[in] stride stride for accessing consecutive elements, defaults to the size of one element. + */ + explicit PX_INLINE PxStrideIterator(T* ptr = NULL, PxU32 stride = sizeof(T)) : mPtr(ptr), mStride(stride) + { + PX_SHARED_ASSERT(mStride == 0 || sizeof(T) <= mStride); + } + + /** + \brief Copy constructor. + + \param[in] strideIterator PxStrideIterator to be copied. + */ + PX_INLINE PxStrideIterator(const PxStrideIterator::Type>& strideIterator) + : mPtr(strideIterator.ptr()), mStride(strideIterator.stride()) + { + PX_SHARED_ASSERT(mStride == 0 || sizeof(T) <= mStride); + } + + /** + \brief Get pointer to element. + */ + PX_INLINE T* ptr() const + { + return mPtr; + } + + /** + \brief Get stride. + */ + PX_INLINE PxU32 stride() const + { + return mStride; + } + + /** + \brief Indirection operator. + */ + PX_INLINE T& operator*() const + { + return *mPtr; + } + + /** + \brief Dereferencing operator. + */ + PX_INLINE T* operator->() const + { + return mPtr; + } + + /** + \brief Indexing operator. + */ + PX_INLINE T& operator[](unsigned int i) const + { + return *byteAdd(mPtr, i * stride()); + } + + /** + \brief Pre-increment operator. + */ + PX_INLINE PxStrideIterator& operator++() + { + mPtr = byteAdd(mPtr, stride()); + return *this; + } + + /** + \brief Post-increment operator. + */ + PX_INLINE PxStrideIterator operator++(int) + { + PxStrideIterator tmp = *this; + mPtr = byteAdd(mPtr, stride()); + return tmp; + } + + /** + \brief Pre-decrement operator. + */ + PX_INLINE PxStrideIterator& operator--() + { + mPtr = byteSub(mPtr, stride()); + return *this; + } + + /** + \brief Post-decrement operator. + */ + PX_INLINE PxStrideIterator operator--(int) + { + PxStrideIterator tmp = *this; + mPtr = byteSub(mPtr, stride()); + return tmp; + } + + /** + \brief Addition operator. + */ + PX_INLINE PxStrideIterator operator+(unsigned int i) const + { + return PxStrideIterator(byteAdd(mPtr, i * stride()), stride()); + } + + /** + \brief Subtraction operator. + */ + PX_INLINE PxStrideIterator operator-(unsigned int i) const + { + return PxStrideIterator(byteSub(mPtr, i * stride()), stride()); + } + + /** + \brief Addition compound assignment operator. + */ + PX_INLINE PxStrideIterator& operator+=(unsigned int i) + { + mPtr = byteAdd(mPtr, i * stride()); + return *this; + } + + /** + \brief Subtraction compound assignment operator. + */ + PX_INLINE PxStrideIterator& operator-=(unsigned int i) + { + mPtr = byteSub(mPtr, i * stride()); + return *this; + } + + /** + \brief Iterator difference. + */ + PX_INLINE int operator-(const PxStrideIterator& other) const + { + PX_SHARED_ASSERT(isCompatible(other)); + int byteDiff = static_cast(reinterpret_cast(mPtr) - reinterpret_cast(other.mPtr)); + return byteDiff / static_cast(stride()); + } + + /** + \brief Equality operator. + */ + PX_INLINE bool operator==(const PxStrideIterator& other) const + { + PX_SHARED_ASSERT(isCompatible(other)); + return mPtr == other.mPtr; + } + + /** + \brief Inequality operator. + */ + PX_INLINE bool operator!=(const PxStrideIterator& other) const + { + PX_SHARED_ASSERT(isCompatible(other)); + return mPtr != other.mPtr; + } + + /** + \brief Less than operator. + */ + PX_INLINE bool operator<(const PxStrideIterator& other) const + { + PX_SHARED_ASSERT(isCompatible(other)); + return mPtr < other.mPtr; + } + + /** + \brief Greater than operator. + */ + PX_INLINE bool operator>(const PxStrideIterator& other) const + { + PX_SHARED_ASSERT(isCompatible(other)); + return mPtr > other.mPtr; + } + + /** + \brief Less or equal than operator. + */ + PX_INLINE bool operator<=(const PxStrideIterator& other) const + { + PX_SHARED_ASSERT(isCompatible(other)); + return mPtr <= other.mPtr; + } + + /** + \brief Greater or equal than operator. + */ + PX_INLINE bool operator>=(const PxStrideIterator& other) const + { + PX_SHARED_ASSERT(isCompatible(other)); + return mPtr >= other.mPtr; + } + + private: + PX_INLINE static T* byteAdd(T* ptr, PxU32 bytes) + { + return const_cast(reinterpret_cast(reinterpret_cast(ptr) + bytes)); + } + + PX_INLINE static T* byteSub(T* ptr, PxU32 bytes) + { + return const_cast(reinterpret_cast(reinterpret_cast(ptr) - bytes)); + } + + PX_INLINE bool isCompatible(const PxStrideIterator& other) const + { + int byteDiff = static_cast(reinterpret_cast(mPtr) - reinterpret_cast(other.mPtr)); + return (stride() == other.stride()) && (abs(byteDiff) % stride() == 0); + } + + T* mPtr; + PxU32 mStride; +}; + +/** +\brief Addition operator. +*/ +template +PX_INLINE PxStrideIterator operator+(int i, PxStrideIterator it) +{ + it += i; + return it; +} + +/** +\brief Stride iterator factory function which infers the iterator type. +*/ +template +PX_INLINE PxStrideIterator PxMakeIterator(T* ptr, PxU32 stride = sizeof(T)) +{ + return PxStrideIterator(ptr, stride); +} + +/** +\brief Stride iterator factory function which infers the iterator type. +*/ +template +PX_INLINE PxStrideIterator PxMakeIterator(const T* ptr, PxU32 stride = sizeof(T)) +{ + return PxStrideIterator(ptr, stride); +} + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif // PXFOUNDATION_PXSTRIDEITERATOR_H diff --git a/sources/PhysX/PxShared/include/foundation/PxTransform.h b/sources/PhysX/PxShared/include/foundation/PxTransform.h new file mode 100644 index 00000000..f639903b --- /dev/null +++ b/sources/PhysX/PxShared/include/foundation/PxTransform.h @@ -0,0 +1,215 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PXFOUNDATION_PXTRANSFORM_H +#define PXFOUNDATION_PXTRANSFORM_H +/** \addtogroup foundation + @{ +*/ + +#include "foundation/PxQuat.h" +#include "foundation/PxPlane.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/*! +\brief class representing a rigid euclidean transform as a quaternion and a vector +*/ + +class PxTransform +{ + public: + PxQuat q; + PxVec3 p; + + PX_CUDA_CALLABLE PX_FORCE_INLINE PxTransform() + { + } + + PX_CUDA_CALLABLE PX_FORCE_INLINE explicit PxTransform(const PxVec3& position) : q(PxIdentity), p(position) + { + } + + PX_CUDA_CALLABLE PX_FORCE_INLINE explicit PxTransform(PxIDENTITY r) : q(PxIdentity), p(PxZero) + { + PX_UNUSED(r); + } + + PX_CUDA_CALLABLE PX_FORCE_INLINE explicit PxTransform(const PxQuat& orientation) : q(orientation), p(0) + { + PX_SHARED_ASSERT(orientation.isSane()); + } + + PX_CUDA_CALLABLE PX_FORCE_INLINE PxTransform(float x, float y, float z, PxQuat aQ = PxQuat(PxIdentity)) + : q(aQ), p(x, y, z) + { + } + + PX_CUDA_CALLABLE PX_FORCE_INLINE PxTransform(const PxVec3& p0, const PxQuat& q0) : q(q0), p(p0) + { + PX_SHARED_ASSERT(q0.isSane()); + } + + PX_CUDA_CALLABLE PX_FORCE_INLINE explicit PxTransform(const PxMat44& m); // defined in PxMat44.h + + /** + \brief returns true if the two transforms are exactly equal + */ + PX_CUDA_CALLABLE PX_INLINE bool operator==(const PxTransform& t) const + { + return p == t.p && q == t.q; + } + + PX_CUDA_CALLABLE PX_FORCE_INLINE PxTransform operator*(const PxTransform& x) const + { + PX_SHARED_ASSERT(x.isSane()); + return transform(x); + } + + //! Equals matrix multiplication + PX_CUDA_CALLABLE PX_INLINE PxTransform& operator*=(PxTransform& other) + { + *this = *this * other; + return *this; + } + + PX_CUDA_CALLABLE PX_FORCE_INLINE PxTransform getInverse() const + { + PX_SHARED_ASSERT(isFinite()); + return PxTransform(q.rotateInv(-p), q.getConjugate()); + } + + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 transform(const PxVec3& input) const + { + PX_SHARED_ASSERT(isFinite()); + return q.rotate(input) + p; + } + + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 transformInv(const PxVec3& input) const + { + PX_SHARED_ASSERT(isFinite()); + return q.rotateInv(input - p); + } + + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 rotate(const PxVec3& input) const + { + PX_SHARED_ASSERT(isFinite()); + return q.rotate(input); + } + + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 rotateInv(const PxVec3& input) const + { + PX_SHARED_ASSERT(isFinite()); + return q.rotateInv(input); + } + + //! Transform transform to parent (returns compound transform: first src, then *this) + PX_CUDA_CALLABLE PX_FORCE_INLINE PxTransform transform(const PxTransform& src) const + { + PX_SHARED_ASSERT(src.isSane()); + PX_SHARED_ASSERT(isSane()); + // src = [srct, srcr] -> [r*srct + t, r*srcr] + return PxTransform(q.rotate(src.p) + p, q * src.q); + } + + /** + \brief returns true if finite and q is a unit quaternion + */ + + PX_CUDA_CALLABLE bool isValid() const + { + return p.isFinite() && q.isFinite() && q.isUnit(); + } + + /** + \brief returns true if finite and quat magnitude is reasonably close to unit to allow for some accumulation of error + vs isValid + */ + + PX_CUDA_CALLABLE bool isSane() const + { + return isFinite() && q.isSane(); + } + + /** + \brief returns true if all elems are finite (not NAN or INF, etc.) + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE bool isFinite() const + { + return p.isFinite() && q.isFinite(); + } + + //! Transform transform from parent (returns compound transform: first src, then this->inverse) + PX_CUDA_CALLABLE PX_FORCE_INLINE PxTransform transformInv(const PxTransform& src) const + { + PX_SHARED_ASSERT(src.isSane()); + PX_SHARED_ASSERT(isFinite()); + // src = [srct, srcr] -> [r^-1*(srct-t), r^-1*srcr] + PxQuat qinv = q.getConjugate(); + return PxTransform(qinv.rotate(src.p - p), qinv * src.q); + } + + /** + \brief transform plane + */ + + PX_CUDA_CALLABLE PX_FORCE_INLINE PxPlane transform(const PxPlane& plane) const + { + PxVec3 transformedNormal = rotate(plane.n); + return PxPlane(transformedNormal, plane.d - p.dot(transformedNormal)); + } + + /** + \brief inverse-transform plane + */ + + PX_CUDA_CALLABLE PX_FORCE_INLINE PxPlane inverseTransform(const PxPlane& plane) const + { + PxVec3 transformedNormal = rotateInv(plane.n); + return PxPlane(transformedNormal, plane.d + p.dot(plane.n)); + } + + /** + \brief return a normalized transform (i.e. one in which the quaternion has unit magnitude) + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxTransform getNormalized() const + { + return PxTransform(p, q.getNormalized()); + } +}; + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif // #ifndef PXFOUNDATION_PXTRANSFORM_H diff --git a/sources/PhysX/PxShared/include/foundation/PxUnionCast.h b/sources/PhysX/PxShared/include/foundation/PxUnionCast.h new file mode 100644 index 00000000..007493cb --- /dev/null +++ b/sources/PhysX/PxShared/include/foundation/PxUnionCast.h @@ -0,0 +1,73 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PXFOUNDATION_PXUNIONCAST_H +#define PXFOUNDATION_PXUNIONCAST_H + +#include "foundation/Px.h" + +/** \addtogroup foundation +@{ +*/ + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +// Needed for clang 7 +#if PX_CLANG && PX_CLANG_MAJOR >= 7 + #define USE_VOLATILE_UNION volatile +#else + #define USE_VOLATILE_UNION +#endif + +template +PX_FORCE_INLINE A PxUnionCast(B b) +{ + union AB + { + AB(B bb) : _b(bb) + { + } + B _b; + A _a; + } USE_VOLATILE_UNION u(b); + return u._a; +} + +#undef USE_VOLATILE_UNION + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ + +#endif // PXFOUNDATION_PXUNIONCAST_H diff --git a/sources/PhysX/PxShared/include/foundation/PxVec2.h b/sources/PhysX/PxShared/include/foundation/PxVec2.h new file mode 100644 index 00000000..11281115 --- /dev/null +++ b/sources/PhysX/PxShared/include/foundation/PxVec2.h @@ -0,0 +1,347 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PXFOUNDATION_PXVEC2_H +#define PXFOUNDATION_PXVEC2_H + +/** \addtogroup foundation +@{ +*/ + +#include "foundation/PxMath.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief 2 Element vector class. + +This is a 2-dimensional vector class with public data members. +*/ +class PxVec2 +{ + public: + /** + \brief default constructor leaves data uninitialized. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec2() + { + } + + /** + \brief zero constructor. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec2(PxZERO r) : x(0.0f), y(0.0f) + { + PX_UNUSED(r); + } + + /** + \brief Assigns scalar parameter to all elements. + + Useful to initialize to zero or one. + + \param[in] a Value to assign to elements. + */ + explicit PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec2(float a) : x(a), y(a) + { + } + + /** + \brief Initializes from 2 scalar parameters. + + \param[in] nx Value to initialize X component. + \param[in] ny Value to initialize Y component. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec2(float nx, float ny) : x(nx), y(ny) + { + } + + /** + \brief Copy ctor. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec2(const PxVec2& v) : x(v.x), y(v.y) + { + } + + // Operators + + /** + \brief Assignment operator + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec2& operator=(const PxVec2& p) + { + x = p.x; + y = p.y; + return *this; + } + + /** + \brief element access + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE float& operator[](int index) + { + PX_SHARED_ASSERT(index >= 0 && index <= 1); + + return reinterpret_cast(this)[index]; + } + + /** + \brief element access + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE const float& operator[](int index) const + { + PX_SHARED_ASSERT(index >= 0 && index <= 1); + + return reinterpret_cast(this)[index]; + } + + /** + \brief returns true if the two vectors are exactly equal. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE bool operator==(const PxVec2& v) const + { + return x == v.x && y == v.y; + } + + /** + \brief returns true if the two vectors are not exactly equal. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE bool operator!=(const PxVec2& v) const + { + return x != v.x || y != v.y; + } + + /** + \brief tests for exact zero vector + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE bool isZero() const + { + return x == 0.0f && y == 0.0f; + } + + /** + \brief returns true if all 2 elems of the vector are finite (not NAN or INF, etc.) + */ + PX_CUDA_CALLABLE PX_INLINE bool isFinite() const + { + return PxIsFinite(x) && PxIsFinite(y); + } + + /** + \brief is normalized - used by API parameter validation + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE bool isNormalized() const + { + const float unitTolerance = 1e-4f; + return isFinite() && PxAbs(magnitude() - 1) < unitTolerance; + } + + /** + \brief returns the squared magnitude + + Avoids calling PxSqrt()! + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE float magnitudeSquared() const + { + return x * x + y * y; + } + + /** + \brief returns the magnitude + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE float magnitude() const + { + return PxSqrt(magnitudeSquared()); + } + + /** + \brief negation + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec2 operator-() const + { + return PxVec2(-x, -y); + } + + /** + \brief vector addition + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec2 operator+(const PxVec2& v) const + { + return PxVec2(x + v.x, y + v.y); + } + + /** + \brief vector difference + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec2 operator-(const PxVec2& v) const + { + return PxVec2(x - v.x, y - v.y); + } + + /** + \brief scalar post-multiplication + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec2 operator*(float f) const + { + return PxVec2(x * f, y * f); + } + + /** + \brief scalar division + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec2 operator/(float f) const + { + f = 1.0f / f; // PT: inconsistent notation with operator /= + return PxVec2(x * f, y * f); + } + + /** + \brief vector addition + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec2& operator+=(const PxVec2& v) + { + x += v.x; + y += v.y; + return *this; + } + + /** + \brief vector difference + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec2& operator-=(const PxVec2& v) + { + x -= v.x; + y -= v.y; + return *this; + } + + /** + \brief scalar multiplication + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec2& operator*=(float f) + { + x *= f; + y *= f; + return *this; + } + /** + \brief scalar division + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec2& operator/=(float f) + { + f = 1.0f / f; // PT: inconsistent notation with operator / + x *= f; + y *= f; + return *this; + } + + /** + \brief returns the scalar product of this and other. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE float dot(const PxVec2& v) const + { + return x * v.x + y * v.y; + } + + /** return a unit vector */ + + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec2 getNormalized() const + { + const float m = magnitudeSquared(); + return m > 0.0f ? *this * PxRecipSqrt(m) : PxVec2(0, 0); + } + + /** + \brief normalizes the vector in place + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE float normalize() + { + const float m = magnitude(); + if(m > 0.0f) + *this /= m; + return m; + } + + /** + \brief a[i] * b[i], for all i. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec2 multiply(const PxVec2& a) const + { + return PxVec2(x * a.x, y * a.y); + } + + /** + \brief element-wise minimum + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec2 minimum(const PxVec2& v) const + { + return PxVec2(PxMin(x, v.x), PxMin(y, v.y)); + } + + /** + \brief returns MIN(x, y); + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE float minElement() const + { + return PxMin(x, y); + } + + /** + \brief element-wise maximum + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec2 maximum(const PxVec2& v) const + { + return PxVec2(PxMax(x, v.x), PxMax(y, v.y)); + } + + /** + \brief returns MAX(x, y); + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE float maxElement() const + { + return PxMax(x, y); + } + + float x, y; +}; + +PX_CUDA_CALLABLE static PX_FORCE_INLINE PxVec2 operator*(float f, const PxVec2& v) +{ + return PxVec2(f * v.x, f * v.y); +} + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif // #ifndef PXFOUNDATION_PXVEC2_H diff --git a/sources/PhysX/PxShared/include/foundation/PxVec3.h b/sources/PhysX/PxShared/include/foundation/PxVec3.h new file mode 100644 index 00000000..d3baead9 --- /dev/null +++ b/sources/PhysX/PxShared/include/foundation/PxVec3.h @@ -0,0 +1,394 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PXFOUNDATION_PXVEC3_H +#define PXFOUNDATION_PXVEC3_H + +/** \addtogroup foundation +@{ +*/ + +#include "foundation/PxMath.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + +/** +\brief 3 Element vector class. + +This is a 3-dimensional vector class with public data members. +*/ +class PxVec3 +{ + public: + /** + \brief default constructor leaves data uninitialized. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3() + { + } + + /** + \brief zero constructor. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3(PxZERO r) : x(0.0f), y(0.0f), z(0.0f) + { + PX_UNUSED(r); + } + + /** + \brief Assigns scalar parameter to all elements. + + Useful to initialize to zero or one. + + \param[in] a Value to assign to elements. + */ + explicit PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3(float a) : x(a), y(a), z(a) + { + } + + /** + \brief Initializes from 3 scalar parameters. + + \param[in] nx Value to initialize X component. + \param[in] ny Value to initialize Y component. + \param[in] nz Value to initialize Z component. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3(float nx, float ny, float nz) : x(nx), y(ny), z(nz) + { + } + + /** + \brief Copy ctor. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3(const PxVec3& v) : x(v.x), y(v.y), z(v.z) + { + } + + // Operators + + /** + \brief Assignment operator + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3& operator=(const PxVec3& p) + { + x = p.x; + y = p.y; + z = p.z; + return *this; + } + + /** + \brief element access + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE float& operator[](unsigned int index) + { + PX_SHARED_ASSERT(index <= 2); + + return reinterpret_cast(this)[index]; + } + + /** + \brief element access + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE const float& operator[](unsigned int index) const + { + PX_SHARED_ASSERT(index <= 2); + + return reinterpret_cast(this)[index]; + } + + /** + \brief returns true if the two vectors are exactly equal. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE bool operator==(const PxVec3& v) const + { + return x == v.x && y == v.y && z == v.z; + } + + /** + \brief returns true if the two vectors are not exactly equal. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE bool operator!=(const PxVec3& v) const + { + return x != v.x || y != v.y || z != v.z; + } + + /** + \brief tests for exact zero vector + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE bool isZero() const + { + return x == 0.0f && y == 0.0f && z == 0.0f; + } + + /** + \brief returns true if all 3 elems of the vector are finite (not NAN or INF, etc.) + */ + PX_CUDA_CALLABLE PX_INLINE bool isFinite() const + { + return PxIsFinite(x) && PxIsFinite(y) && PxIsFinite(z); + } + + /** + \brief is normalized - used by API parameter validation + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE bool isNormalized() const + { + const float unitTolerance = 1e-4f; + return isFinite() && PxAbs(magnitude() - 1) < unitTolerance; + } + + /** + \brief returns the squared magnitude + + Avoids calling PxSqrt()! + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE float magnitudeSquared() const + { + return x * x + y * y + z * z; + } + + /** + \brief returns the magnitude + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE float magnitude() const + { + return PxSqrt(magnitudeSquared()); + } + + /** + \brief negation + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 operator-() const + { + return PxVec3(-x, -y, -z); + } + + /** + \brief vector addition + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 operator+(const PxVec3& v) const + { + return PxVec3(x + v.x, y + v.y, z + v.z); + } + + /** + \brief vector difference + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 operator-(const PxVec3& v) const + { + return PxVec3(x - v.x, y - v.y, z - v.z); + } + + /** + \brief scalar post-multiplication + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 operator*(float f) const + { + return PxVec3(x * f, y * f, z * f); + } + + /** + \brief scalar division + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 operator/(float f) const + { + f = 1.0f / f; + return PxVec3(x * f, y * f, z * f); + } + + /** + \brief vector addition + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3& operator+=(const PxVec3& v) + { + x += v.x; + y += v.y; + z += v.z; + return *this; + } + + /** + \brief vector difference + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3& operator-=(const PxVec3& v) + { + x -= v.x; + y -= v.y; + z -= v.z; + return *this; + } + + /** + \brief scalar multiplication + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3& operator*=(float f) + { + x *= f; + y *= f; + z *= f; + return *this; + } + /** + \brief scalar division + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3& operator/=(float f) + { + f = 1.0f / f; + x *= f; + y *= f; + z *= f; + return *this; + } + + /** + \brief returns the scalar product of this and other. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE float dot(const PxVec3& v) const + { + return x * v.x + y * v.y + z * v.z; + } + + /** + \brief cross product + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 cross(const PxVec3& v) const + { + return PxVec3(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x); + } + + /** return a unit vector */ + + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 getNormalized() const + { + const float m = magnitudeSquared(); + return m > 0.0f ? *this * PxRecipSqrt(m) : PxVec3(0, 0, 0); + } + + /** + \brief normalizes the vector in place + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE float normalize() + { + const float m = magnitude(); + if(m > 0.0f) + *this /= m; + return m; + } + + /** + \brief normalizes the vector in place. Does nothing if vector magnitude is under PX_NORMALIZATION_EPSILON. + Returns vector magnitude if >= PX_NORMALIZATION_EPSILON and 0.0f otherwise. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE float normalizeSafe() + { + const float mag = magnitude(); + if(mag < PX_NORMALIZATION_EPSILON) + return 0.0f; + *this *= 1.0f / mag; + return mag; + } + + /** + \brief normalizes the vector in place. Asserts if vector magnitude is under PX_NORMALIZATION_EPSILON. + returns vector magnitude. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE float normalizeFast() + { + const float mag = magnitude(); + PX_SHARED_ASSERT(mag >= PX_NORMALIZATION_EPSILON); + *this *= 1.0f / mag; + return mag; + } + + /** + \brief a[i] * b[i], for all i. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 multiply(const PxVec3& a) const + { + return PxVec3(x * a.x, y * a.y, z * a.z); + } + + /** + \brief element-wise minimum + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 minimum(const PxVec3& v) const + { + return PxVec3(PxMin(x, v.x), PxMin(y, v.y), PxMin(z, v.z)); + } + + /** + \brief returns MIN(x, y, z); + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE float minElement() const + { + return PxMin(x, PxMin(y, z)); + } + + /** + \brief element-wise maximum + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 maximum(const PxVec3& v) const + { + return PxVec3(PxMax(x, v.x), PxMax(y, v.y), PxMax(z, v.z)); + } + + /** + \brief returns MAX(x, y, z); + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE float maxElement() const + { + return PxMax(x, PxMax(y, z)); + } + + /** + \brief returns absolute values of components; + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 abs() const + { + return PxVec3(PxAbs(x), PxAbs(y), PxAbs(z)); + } + + float x, y, z; +}; + +PX_CUDA_CALLABLE static PX_FORCE_INLINE PxVec3 operator*(float f, const PxVec3& v) +{ + return PxVec3(f * v.x, f * v.y, f * v.z); +} + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif // #ifndef PXFOUNDATION_PXVEC3_H diff --git a/sources/PhysX/PxShared/include/foundation/PxVec4.h b/sources/PhysX/PxShared/include/foundation/PxVec4.h new file mode 100644 index 00000000..711e5310 --- /dev/null +++ b/sources/PhysX/PxShared/include/foundation/PxVec4.h @@ -0,0 +1,376 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PXFOUNDATION_PXVEC4_H +#define PXFOUNDATION_PXVEC4_H +/** \addtogroup foundation +@{ +*/ +#include "foundation/PxMath.h" +#include "foundation/PxVec3.h" +#include "foundation/PxSharedAssert.h" + +/** +\brief 4 Element vector class. + +This is a 4-dimensional vector class with public data members. +*/ +#if !PX_DOXYGEN +namespace physx +{ +#endif + +class PxVec4 +{ + public: + /** + \brief default constructor leaves data uninitialized. + */ + PX_CUDA_CALLABLE PX_INLINE PxVec4() + { + } + + /** + \brief zero constructor. + */ + PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec4(PxZERO r) : x(0.0f), y(0.0f), z(0.0f), w(0.0f) + { + PX_UNUSED(r); + } + + /** + \brief Assigns scalar parameter to all elements. + + Useful to initialize to zero or one. + + \param[in] a Value to assign to elements. + */ + explicit PX_CUDA_CALLABLE PX_INLINE PxVec4(float a) : x(a), y(a), z(a), w(a) + { + } + + /** + \brief Initializes from 3 scalar parameters. + + \param[in] nx Value to initialize X component. + \param[in] ny Value to initialize Y component. + \param[in] nz Value to initialize Z component. + \param[in] nw Value to initialize W component. + */ + PX_CUDA_CALLABLE PX_INLINE PxVec4(float nx, float ny, float nz, float nw) : x(nx), y(ny), z(nz), w(nw) + { + } + + /** + \brief Initializes from 3 scalar parameters. + + \param[in] v Value to initialize the X, Y, and Z components. + \param[in] nw Value to initialize W component. + */ + PX_CUDA_CALLABLE PX_INLINE PxVec4(const PxVec3& v, float nw) : x(v.x), y(v.y), z(v.z), w(nw) + { + } + + /** + \brief Initializes from an array of scalar parameters. + + \param[in] v Value to initialize with. + */ + explicit PX_CUDA_CALLABLE PX_INLINE PxVec4(const float v[]) : x(v[0]), y(v[1]), z(v[2]), w(v[3]) + { + } + + /** + \brief Copy ctor. + */ + PX_CUDA_CALLABLE PX_INLINE PxVec4(const PxVec4& v) : x(v.x), y(v.y), z(v.z), w(v.w) + { + } + + // Operators + + /** + \brief Assignment operator + */ + PX_CUDA_CALLABLE PX_INLINE PxVec4& operator=(const PxVec4& p) + { + x = p.x; + y = p.y; + z = p.z; + w = p.w; + return *this; + } + + /** + \brief element access + */ + PX_CUDA_CALLABLE PX_INLINE float& operator[](unsigned int index) + { + PX_SHARED_ASSERT(index <= 3); + + return reinterpret_cast(this)[index]; + } + + /** + \brief element access + */ + PX_CUDA_CALLABLE PX_INLINE const float& operator[](unsigned int index) const + { + PX_SHARED_ASSERT(index <= 3); + + return reinterpret_cast(this)[index]; + } + + /** + \brief returns true if the two vectors are exactly equal. + */ + PX_CUDA_CALLABLE PX_INLINE bool operator==(const PxVec4& v) const + { + return x == v.x && y == v.y && z == v.z && w == v.w; + } + + /** + \brief returns true if the two vectors are not exactly equal. + */ + PX_CUDA_CALLABLE PX_INLINE bool operator!=(const PxVec4& v) const + { + return x != v.x || y != v.y || z != v.z || w != v.w; + } + + /** + \brief tests for exact zero vector + */ + PX_CUDA_CALLABLE PX_INLINE bool isZero() const + { + return x == 0 && y == 0 && z == 0 && w == 0; + } + + /** + \brief returns true if all 3 elems of the vector are finite (not NAN or INF, etc.) + */ + PX_CUDA_CALLABLE PX_INLINE bool isFinite() const + { + return PxIsFinite(x) && PxIsFinite(y) && PxIsFinite(z) && PxIsFinite(w); + } + + /** + \brief is normalized - used by API parameter validation + */ + PX_CUDA_CALLABLE PX_INLINE bool isNormalized() const + { + const float unitTolerance = 1e-4f; + return isFinite() && PxAbs(magnitude() - 1) < unitTolerance; + } + + /** + \brief returns the squared magnitude + + Avoids calling PxSqrt()! + */ + PX_CUDA_CALLABLE PX_INLINE float magnitudeSquared() const + { + return x * x + y * y + z * z + w * w; + } + + /** + \brief returns the magnitude + */ + PX_CUDA_CALLABLE PX_INLINE float magnitude() const + { + return PxSqrt(magnitudeSquared()); + } + + /** + \brief negation + */ + PX_CUDA_CALLABLE PX_INLINE PxVec4 operator-() const + { + return PxVec4(-x, -y, -z, -w); + } + + /** + \brief vector addition + */ + PX_CUDA_CALLABLE PX_INLINE PxVec4 operator+(const PxVec4& v) const + { + return PxVec4(x + v.x, y + v.y, z + v.z, w + v.w); + } + + /** + \brief vector difference + */ + PX_CUDA_CALLABLE PX_INLINE PxVec4 operator-(const PxVec4& v) const + { + return PxVec4(x - v.x, y - v.y, z - v.z, w - v.w); + } + + /** + \brief scalar post-multiplication + */ + + PX_CUDA_CALLABLE PX_INLINE PxVec4 operator*(float f) const + { + return PxVec4(x * f, y * f, z * f, w * f); + } + + /** + \brief scalar division + */ + PX_CUDA_CALLABLE PX_INLINE PxVec4 operator/(float f) const + { + f = 1.0f / f; + return PxVec4(x * f, y * f, z * f, w * f); + } + + /** + \brief vector addition + */ + PX_CUDA_CALLABLE PX_INLINE PxVec4& operator+=(const PxVec4& v) + { + x += v.x; + y += v.y; + z += v.z; + w += v.w; + return *this; + } + + /** + \brief vector difference + */ + PX_CUDA_CALLABLE PX_INLINE PxVec4& operator-=(const PxVec4& v) + { + x -= v.x; + y -= v.y; + z -= v.z; + w -= v.w; + return *this; + } + + /** + \brief scalar multiplication + */ + PX_CUDA_CALLABLE PX_INLINE PxVec4& operator*=(float f) + { + x *= f; + y *= f; + z *= f; + w *= f; + return *this; + } + /** + \brief scalar division + */ + PX_CUDA_CALLABLE PX_INLINE PxVec4& operator/=(float f) + { + f = 1.0f / f; + x *= f; + y *= f; + z *= f; + w *= f; + return *this; + } + + /** + \brief returns the scalar product of this and other. + */ + PX_CUDA_CALLABLE PX_INLINE float dot(const PxVec4& v) const + { + return x * v.x + y * v.y + z * v.z + w * v.w; + } + + /** return a unit vector */ + + PX_CUDA_CALLABLE PX_INLINE PxVec4 getNormalized() const + { + float m = magnitudeSquared(); + return m > 0.0f ? *this * PxRecipSqrt(m) : PxVec4(0, 0, 0, 0); + } + + /** + \brief normalizes the vector in place + */ + PX_CUDA_CALLABLE PX_INLINE float normalize() + { + float m = magnitude(); + if(m > 0.0f) + *this /= m; + return m; + } + + /** + \brief a[i] * b[i], for all i. + */ + PX_CUDA_CALLABLE PX_INLINE PxVec4 multiply(const PxVec4& a) const + { + return PxVec4(x * a.x, y * a.y, z * a.z, w * a.w); + } + + /** + \brief element-wise minimum + */ + PX_CUDA_CALLABLE PX_INLINE PxVec4 minimum(const PxVec4& v) const + { + return PxVec4(PxMin(x, v.x), PxMin(y, v.y), PxMin(z, v.z), PxMin(w, v.w)); + } + + /** + \brief element-wise maximum + */ + PX_CUDA_CALLABLE PX_INLINE PxVec4 maximum(const PxVec4& v) const + { + return PxVec4(PxMax(x, v.x), PxMax(y, v.y), PxMax(z, v.z), PxMax(w, v.w)); + } + + PX_CUDA_CALLABLE PX_INLINE PxVec3 getXYZ() const + { + return PxVec3(x, y, z); + } + + /** + \brief set vector elements to zero + */ + PX_CUDA_CALLABLE PX_INLINE void setZero() + { + x = y = z = w = 0.0f; + } + + float x, y, z, w; +}; + +PX_CUDA_CALLABLE static PX_INLINE PxVec4 operator*(float f, const PxVec4& v) +{ + return PxVec4(f * v.x, f * v.y, f * v.z, f * v.w); +} + +#if !PX_DOXYGEN +} // namespace physx +#endif + +/** @} */ +#endif // #ifndef PXFOUNDATION_PXVEC4_H diff --git a/sources/PhysX/PxShared/include/foundation/unix/PxUnixIntrinsics.h b/sources/PhysX/PxShared/include/foundation/unix/PxUnixIntrinsics.h new file mode 100644 index 00000000..1095b135 --- /dev/null +++ b/sources/PhysX/PxShared/include/foundation/unix/PxUnixIntrinsics.h @@ -0,0 +1,185 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PXFOUNDATION_PXUNIXINTRINSICS_H +#define PXFOUNDATION_PXUNIXINTRINSICS_H + +#include "foundation/Px.h" +#include "foundation/PxSharedAssert.h" + +#if !(PX_LINUX || PX_ANDROID || PX_PS4 || PX_APPLE_FAMILY) +#error "This file should only be included by Unix builds!!" +#endif + +#if (PX_LINUX || PX_ANDROID) && !defined(__CUDACC__) && !PX_EMSCRIPTEN + // Linux/android and CUDA compilation does not work with std::isfnite, as it is not marked as CUDA callable + #include + #ifndef isfinite + using std::isfinite; + #endif +#endif + +#include +#include + +namespace physx +{ +namespace intrinsics +{ +//! \brief platform-specific absolute value +PX_CUDA_CALLABLE PX_FORCE_INLINE float abs(float a) +{ + return ::fabsf(a); +} + +//! \brief platform-specific select float +PX_CUDA_CALLABLE PX_FORCE_INLINE float fsel(float a, float b, float c) +{ + return (a >= 0.0f) ? b : c; +} + +//! \brief platform-specific sign +PX_CUDA_CALLABLE PX_FORCE_INLINE float sign(float a) +{ + return (a >= 0.0f) ? 1.0f : -1.0f; +} + +//! \brief platform-specific reciprocal +PX_CUDA_CALLABLE PX_FORCE_INLINE float recip(float a) +{ + return 1.0f / a; +} + +//! \brief platform-specific reciprocal estimate +PX_CUDA_CALLABLE PX_FORCE_INLINE float recipFast(float a) +{ + return 1.0f / a; +} + +//! \brief platform-specific square root +PX_CUDA_CALLABLE PX_FORCE_INLINE float sqrt(float a) +{ + return ::sqrtf(a); +} + +//! \brief platform-specific reciprocal square root +PX_CUDA_CALLABLE PX_FORCE_INLINE float recipSqrt(float a) +{ + return 1.0f / ::sqrtf(a); +} + +PX_CUDA_CALLABLE PX_FORCE_INLINE float recipSqrtFast(float a) +{ + return 1.0f / ::sqrtf(a); +} + +//! \brief platform-specific sine +PX_CUDA_CALLABLE PX_FORCE_INLINE float sin(float a) +{ + return ::sinf(a); +} + +//! \brief platform-specific cosine +PX_CUDA_CALLABLE PX_FORCE_INLINE float cos(float a) +{ + return ::cosf(a); +} + +//! \brief platform-specific minimum +PX_CUDA_CALLABLE PX_FORCE_INLINE float selectMin(float a, float b) +{ + return a < b ? a : b; +} + +//! \brief platform-specific maximum +PX_CUDA_CALLABLE PX_FORCE_INLINE float selectMax(float a, float b) +{ + return a > b ? a : b; +} + +//! \brief platform-specific finiteness check (not INF or NAN) +PX_CUDA_CALLABLE PX_FORCE_INLINE bool isFinite(float a) +{ + //std::isfinite not recommended as of Feb 2017, since it doesn't work with g++/clang's floating point optimization. + union localU { PxU32 i; float f; } floatUnion; + floatUnion.f = a; + return !((floatUnion.i & 0x7fffffff) >= 0x7f800000); +} + +//! \brief platform-specific finiteness check (not INF or NAN) +PX_CUDA_CALLABLE PX_FORCE_INLINE bool isFinite(double a) +{ + return !!isfinite(a); +} + +/*! +Sets \c count bytes starting at \c dst to zero. +*/ +PX_FORCE_INLINE void* memZero(void* dest, uint32_t count) +{ + return memset(dest, 0, count); +} + +/*! +Sets \c count bytes starting at \c dst to \c c. +*/ +PX_FORCE_INLINE void* memSet(void* dest, int32_t c, uint32_t count) +{ + return memset(dest, c, count); +} + +/*! +Copies \c count bytes from \c src to \c dst. User memMove if regions overlap. +*/ +PX_FORCE_INLINE void* memCopy(void* dest, const void* src, uint32_t count) +{ + return memcpy(dest, src, count); +} + +/*! +Copies \c count bytes from \c src to \c dst. Supports overlapping regions. +*/ +PX_FORCE_INLINE void* memMove(void* dest, const void* src, uint32_t count) +{ + return memmove(dest, src, count); +} + +/*! +Set 128B to zero starting at \c dst+offset. Must be aligned. +*/ +PX_FORCE_INLINE void memZero128(void* dest, uint32_t offset = 0) +{ + PX_SHARED_ASSERT(((size_t(dest) + offset) & 0x7f) == 0); + memSet(reinterpret_cast(dest) + offset, 0, 128); +} + +} // namespace intrinsics +} // namespace physx + +#endif // #ifndef PXFOUNDATION_PXUNIXINTRINSICS_H diff --git a/sources/PhysX/PxShared/include/foundation/windows/PxWindowsIntrinsics.h b/sources/PhysX/PxShared/include/foundation/windows/PxWindowsIntrinsics.h new file mode 100644 index 00000000..804c20b0 --- /dev/null +++ b/sources/PhysX/PxShared/include/foundation/windows/PxWindowsIntrinsics.h @@ -0,0 +1,188 @@ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PXFOUNDATION_PXWINDOWSINTRINSICS_H +#define PXFOUNDATION_PXWINDOWSINTRINSICS_H + +#include "foundation/Px.h" +#include "foundation/PxSharedAssert.h" + +#if !PX_WINDOWS_FAMILY +#error "This file should only be included by Windows builds!!" +#endif + +#include +#include + +#if !PX_DOXYGEN +namespace physx +{ +namespace intrinsics +{ +#endif + +//! \brief platform-specific absolute value +PX_CUDA_CALLABLE PX_FORCE_INLINE float abs(float a) +{ + return ::fabsf(a); +} + +//! \brief platform-specific select float +PX_CUDA_CALLABLE PX_FORCE_INLINE float fsel(float a, float b, float c) +{ + return (a >= 0.0f) ? b : c; +} + +//! \brief platform-specific sign +PX_CUDA_CALLABLE PX_FORCE_INLINE float sign(float a) +{ + return (a >= 0.0f) ? 1.0f : -1.0f; +} + +//! \brief platform-specific reciprocal +PX_CUDA_CALLABLE PX_FORCE_INLINE float recip(float a) +{ + return 1.0f / a; +} + +//! \brief platform-specific reciprocal estimate +PX_CUDA_CALLABLE PX_FORCE_INLINE float recipFast(float a) +{ + return 1.0f / a; +} + +//! \brief platform-specific square root +PX_CUDA_CALLABLE PX_FORCE_INLINE float sqrt(float a) +{ + return ::sqrtf(a); +} + +//! \brief platform-specific reciprocal square root +PX_CUDA_CALLABLE PX_FORCE_INLINE float recipSqrt(float a) +{ + return 1.0f / ::sqrtf(a); +} + +//! \brief platform-specific reciprocal square root estimate +PX_CUDA_CALLABLE PX_FORCE_INLINE float recipSqrtFast(float a) +{ + return 1.0f / ::sqrtf(a); +} + +//! \brief platform-specific sine +PX_CUDA_CALLABLE PX_FORCE_INLINE float sin(float a) +{ + return ::sinf(a); +} + +//! \brief platform-specific cosine +PX_CUDA_CALLABLE PX_FORCE_INLINE float cos(float a) +{ + return ::cosf(a); +} + +//! \brief platform-specific minimum +PX_CUDA_CALLABLE PX_FORCE_INLINE float selectMin(float a, float b) +{ + return a < b ? a : b; +} + +//! \brief platform-specific maximum +PX_CUDA_CALLABLE PX_FORCE_INLINE float selectMax(float a, float b) +{ + return a > b ? a : b; +} + +//! \brief platform-specific finiteness check (not INF or NAN) +PX_CUDA_CALLABLE PX_FORCE_INLINE bool isFinite(float a) +{ +#ifdef __CUDACC__ + return !!isfinite(a); +#else + return (0 == ((_FPCLASS_SNAN | _FPCLASS_QNAN | _FPCLASS_NINF | _FPCLASS_PINF) & _fpclass(a))); +#endif +} + +//! \brief platform-specific finiteness check (not INF or NAN) +PX_CUDA_CALLABLE PX_FORCE_INLINE bool isFinite(double a) +{ +#ifdef __CUDACC__ + return !!isfinite(a); +#else + return (0 == ((_FPCLASS_SNAN | _FPCLASS_QNAN | _FPCLASS_NINF | _FPCLASS_PINF) & _fpclass(a))); +#endif +} + +/*! +Sets \c count bytes starting at \c dst to zero. +*/ +PX_FORCE_INLINE void* memZero(void* dest, uint32_t count) +{ + return memset(dest, 0, count); +} + +/*! +Sets \c count bytes starting at \c dst to \c c. +*/ +PX_FORCE_INLINE void* memSet(void* dest, int32_t c, uint32_t count) +{ + return memset(dest, c, count); +} + +/*! +Copies \c count bytes from \c src to \c dst. User memMove if regions overlap. +*/ +PX_FORCE_INLINE void* memCopy(void* dest, const void* src, uint32_t count) +{ + return memcpy(dest, src, count); +} + +/*! +Copies \c count bytes from \c src to \c dst. Supports overlapping regions. +*/ +PX_FORCE_INLINE void* memMove(void* dest, const void* src, uint32_t count) +{ + return memmove(dest, src, count); +} + +/*! +Set 128B to zero starting at \c dst+offset. Must be aligned. +*/ +PX_FORCE_INLINE void memZero128(void* dest, uint32_t offset = 0) +{ + PX_SHARED_ASSERT(((size_t(dest) + offset) & 0x7f) == 0); + memSet(reinterpret_cast(dest) + offset, 0, 128); +} + +#if !PX_DOXYGEN +} // namespace intrinsics +} // namespace physx +#endif + +#endif // #ifndef PXFOUNDATION_PXWINDOWSINTRINSICS_H diff --git a/win32/CMakeLists.txt b/win32/CMakeLists.txt index a8e0754c..cb341642 100644 --- a/win32/CMakeLists.txt +++ b/win32/CMakeLists.txt @@ -243,6 +243,19 @@ list(APPEND CC_EXTERNAL_PRIVATE_DEFINITIONS $, __TBB_LIB_NAME=tbb_static_debug, __TBB_LIB_NAME=tbb_static> ) +if(USE_PHYSICS_PHYSX) + set(PhysXSDK PhysX PhysXCommon PhysXFoundation PhysXExtensions PhysXCooking PhysXCharacterKinematic PhysXVehicle PhysXPvdSDK) + foreach(PX IN LISTS PhysXSDK) + add_library(${PX} STATIC IMPORTED GLOBAL) + set_target_properties(${PX} PROPERTIES + IMPORTED_LOCATION_DEBUG ${CMAKE_CURRENT_LIST_DIR}/libs/PhysX/debug/${PX}_static_32.lib + IMPORTED_LOCATION_RELEASE ${CMAKE_CURRENT_LIST_DIR}/libs/PhysX/release/${PX}_static_32.lib + ) + endforeach() +else() + set(PhysXSDK) +endif() + list(APPEND CC_EXTERNAL_LIBS freetype glew32 @@ -267,6 +280,7 @@ list(APPEND CC_EXTERNAL_LIBS SDL2Main ${glslang_libs_name} ${tbb_libs_name} + ${PhysXSDK} ) diff --git a/win32/libs/PhysX/debug/PhysXCharacterKinematic_static_32.lib b/win32/libs/PhysX/debug/PhysXCharacterKinematic_static_32.lib new file mode 100644 index 00000000..789e6407 Binary files /dev/null and b/win32/libs/PhysX/debug/PhysXCharacterKinematic_static_32.lib differ diff --git a/win32/libs/PhysX/debug/PhysXCommon_static_32.lib b/win32/libs/PhysX/debug/PhysXCommon_static_32.lib new file mode 100644 index 00000000..50091f8a Binary files /dev/null and b/win32/libs/PhysX/debug/PhysXCommon_static_32.lib differ diff --git a/win32/libs/PhysX/debug/PhysXCooking_static_32.lib b/win32/libs/PhysX/debug/PhysXCooking_static_32.lib new file mode 100644 index 00000000..bf899ac1 Binary files /dev/null and b/win32/libs/PhysX/debug/PhysXCooking_static_32.lib differ diff --git a/win32/libs/PhysX/debug/PhysXExtensions_static_32.lib b/win32/libs/PhysX/debug/PhysXExtensions_static_32.lib new file mode 100644 index 00000000..b72baac2 Binary files /dev/null and b/win32/libs/PhysX/debug/PhysXExtensions_static_32.lib differ diff --git a/win32/libs/PhysX/debug/PhysXFoundation_static_32.lib b/win32/libs/PhysX/debug/PhysXFoundation_static_32.lib new file mode 100644 index 00000000..c92cb564 Binary files /dev/null and b/win32/libs/PhysX/debug/PhysXFoundation_static_32.lib differ diff --git a/win32/libs/PhysX/debug/PhysXPvdSDK_static_32.lib b/win32/libs/PhysX/debug/PhysXPvdSDK_static_32.lib new file mode 100644 index 00000000..727db072 Binary files /dev/null and b/win32/libs/PhysX/debug/PhysXPvdSDK_static_32.lib differ diff --git a/win32/libs/PhysX/debug/PhysXVehicle_static_32.lib b/win32/libs/PhysX/debug/PhysXVehicle_static_32.lib new file mode 100644 index 00000000..e0d4bea6 Binary files /dev/null and b/win32/libs/PhysX/debug/PhysXVehicle_static_32.lib differ diff --git a/win32/libs/PhysX/debug/PhysX_static_32.lib b/win32/libs/PhysX/debug/PhysX_static_32.lib new file mode 100644 index 00000000..97218a0b Binary files /dev/null and b/win32/libs/PhysX/debug/PhysX_static_32.lib differ diff --git a/win32/libs/PhysX/release/PhysXCharacterKinematic_static_32.lib b/win32/libs/PhysX/release/PhysXCharacterKinematic_static_32.lib new file mode 100644 index 00000000..02374ebc Binary files /dev/null and b/win32/libs/PhysX/release/PhysXCharacterKinematic_static_32.lib differ diff --git a/win32/libs/PhysX/release/PhysXCommon_static_32.lib b/win32/libs/PhysX/release/PhysXCommon_static_32.lib new file mode 100644 index 00000000..30e78911 Binary files /dev/null and b/win32/libs/PhysX/release/PhysXCommon_static_32.lib differ diff --git a/win32/libs/PhysX/release/PhysXCooking_static_32.lib b/win32/libs/PhysX/release/PhysXCooking_static_32.lib new file mode 100644 index 00000000..4af21819 Binary files /dev/null and b/win32/libs/PhysX/release/PhysXCooking_static_32.lib differ diff --git a/win32/libs/PhysX/release/PhysXExtensions_static_32.lib b/win32/libs/PhysX/release/PhysXExtensions_static_32.lib new file mode 100644 index 00000000..c7e5d241 Binary files /dev/null and b/win32/libs/PhysX/release/PhysXExtensions_static_32.lib differ diff --git a/win32/libs/PhysX/release/PhysXFoundation_static_32.lib b/win32/libs/PhysX/release/PhysXFoundation_static_32.lib new file mode 100644 index 00000000..b728f953 Binary files /dev/null and b/win32/libs/PhysX/release/PhysXFoundation_static_32.lib differ diff --git a/win32/libs/PhysX/release/PhysXPvdSDK_static_32.lib b/win32/libs/PhysX/release/PhysXPvdSDK_static_32.lib new file mode 100644 index 00000000..2aedc964 Binary files /dev/null and b/win32/libs/PhysX/release/PhysXPvdSDK_static_32.lib differ diff --git a/win32/libs/PhysX/release/PhysXVehicle_static_32.lib b/win32/libs/PhysX/release/PhysXVehicle_static_32.lib new file mode 100644 index 00000000..822f1873 Binary files /dev/null and b/win32/libs/PhysX/release/PhysXVehicle_static_32.lib differ diff --git a/win32/libs/PhysX/release/PhysX_static_32.lib b/win32/libs/PhysX/release/PhysX_static_32.lib new file mode 100644 index 00000000..f4f793a1 Binary files /dev/null and b/win32/libs/PhysX/release/PhysX_static_32.lib differ