diff --git a/physx/.gitignore b/physx/.gitignore
index dc0d38c20..52667b497 100644
--- a/physx/.gitignore
+++ b/physx/.gitignore
@@ -1,4 +1,3 @@
-bin/
compiler/linux-*
compiler/vc*
include/PxConfig.h
diff --git a/physx/CHANGELOG.md b/physx/CHANGELOG.md
index 6dc5ef6c7..2b11f0637 100644
--- a/physx/CHANGELOG.md
+++ b/physx/CHANGELOG.md
@@ -1,3 +1,40 @@
+# v5.4.1-106.0
+
+## General
+
+### Added
+
+* Debug visualization of contact friction was added, controlled by the following visualization parameter flags: PxVisualizationParameter::eFRICTION_POINT, PxVisualizationParameter::eFRICTION_NORMAL, and PxVisualizationParameter::eFRICTION_IMPULSE.
+* PxVisualizationParameter::eCONTACT_IMPULSE flag was added to replace PxVisualizationParameter::eCONTACT_FORCE.
+
+### Deprecated
+
+* PxVisualizationParameter::eCONTACT_FORCE was deprecated. Use PxVisualizationParameter::eCONTACT_IMPULSE instead.
+
+### Fixed
+
+* A bug in Debug Visualization where collision contact points are misaligned with collision geometry.
+* A bug in the GPU broadphase that resulted in a crash when overflowing the preallocated number of lost and found pairs.
+
+## Articulations
+
+### Added
+
+* Possibility to apply a force or a torque to an articulation link through articulation cache with the flags PxArticulationCacheFlag::eLINK_FORCE and PxArticulationCacheFlag::eLINK_TORQUE.
+
+### Fixed
+
+* Runtime changes to PxArticulationJointReducedCoordinate::setMaxJointVelocity() were not working for the GPU pipeline.
+* Runtime changes to PxArticulationJointReducedCoordinate::setFrictionCoefficient() were not working for the GPU pipeline.
+* A bug when adding articulations to a scene that already contained other articulations.
+* Corrected the calculation of the first tangent vector used in the friction patch model of articulations. This may have increased the probability of artifacts in the friction calculation.
+
+## PVD
+
+### Fixed
+
+* Missing OVD object creation calls in deserializations of PxCollection and PxAggregate with regards to articulations.
+
# v5.4.0-106.0
## Supported Platforms
@@ -5,7 +42,6 @@
### Runtime
* Linux (tested on Ubuntu 20.04 and 22.04)
-* Linux glibc version 2.31 or higher
* Microsoft Windows 10 or later (64 bit)
* GPU acceleration: display driver supporting CUDA toolkit 11.8 and Pascal GPU or above
diff --git a/physx/dependencies.xml b/physx/dependencies.xml
index 5adb56ac8..44c74d2dc 100644
--- a/physx/dependencies.xml
+++ b/physx/dependencies.xml
@@ -16,9 +16,9 @@
-
-
-
+
+
+
diff --git a/physx/documentation/platformreadme/linux/README_LINUX.md b/physx/documentation/platformreadme/linux/README_LINUX.md
index d481f2654..d2920a290 100644
--- a/physx/documentation/platformreadme/linux/README_LINUX.md
+++ b/physx/documentation/platformreadme/linux/README_LINUX.md
@@ -18,7 +18,7 @@ Compilers and C++ Standard:
* Ubuntu 22.04 LTS with gcc 11 or clang 14
* Note: PhysX may fail to compile with clang versions higher than 14 as they have not been tested
* For linux aarch64 builds we support gcc version 9
- * C++17 compatible
+ * Tested with C++11 standard
## Generating Makefiles:
diff --git a/physx/documentation/platformreadme/windows/README_WINDOWS.md b/physx/documentation/platformreadme/windows/README_WINDOWS.md
index 4b0e679a4..7fe626eda 100644
--- a/physx/documentation/platformreadme/windows/README_WINDOWS.md
+++ b/physx/documentation/platformreadme/windows/README_WINDOWS.md
@@ -7,13 +7,13 @@
## Required packages to generate projects:
-* Microsoft Windows 10 (or later) + headers for at least Win7 (`_WIN32_WINNT = 0x0601`)
+* Microsoft Windows 10 (or later)
* CMake, minimum version 3.21
* Python, minimum version 3.5
Compilers and C++ Standard:
* Microsoft Visual Studio 2017, 2019, 2022 (64 bit)
- * C++17 compatible
+ * Tested with C++14 standard
## PhysX GPU Acceleration:
diff --git a/physx/generate_projects.bat b/physx/generate_projects.bat
index fb7ba5ead..52e3a729c 100644
--- a/physx/generate_projects.bat
+++ b/physx/generate_projects.bat
@@ -24,11 +24,19 @@ for /f "usebackq tokens=*" %%i in (`"%PM_vswhere_PATH%\VsWhere.exe -version [15
for /f "usebackq tokens=*" %%i in (`"%PM_vswhere_PATH%\VsWhere.exe -version [16.0,17.0) -latest -property installationPath"`) do (
set Install2019Dir=%%i
set VS160PATH="%%i"
+ @REM Setting VS160COMNTOOLS: This is mainly needed for building for Switch
+ @REM Reason: When both MS build tools and Visual Studio are installed together in the same system
+ @REM Cmake will use msbuild to generate the project instead of Visual Studio. Which make Cmake fail
+ @REM When generating the project for Switch. However, if an environment variable of the form VS##0COMNTOOLS,
+ @REM where ## the Visual Studio major version number, is set and points to the Common7/Tools directory within
+ @REM one of the VS instances, that instance will be used. see: https://cmake.org/cmake/help/latest/variable/CMAKE_GENERATOR_INSTANCE.html
+ set "VS160COMNTOOLS=%%i\Common7\Tools\"
)
for /f "usebackq tokens=*" %%i in (`"%PM_vswhere_PATH%\VsWhere.exe -version [17.0,18.0) -latest -property installationPath"`) do (
set Install2022Dir=%%i
set VS170PATH="%%i"
+ set "VS170COMNTOOLS=%%i\Common7\Tools\"
)
if exist "%Install2017Dir%\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt" (
diff --git a/physx/include/PxArticulationFlag.h b/physx/include/PxArticulationFlag.h
index b0920418b..c5c644ce9 100644
--- a/physx/include/PxArticulationFlag.h
+++ b/physx/include/PxArticulationFlag.h
@@ -92,11 +92,13 @@ namespace physx
eFORCE = (1 << 3), //!< The joint forces, see PxArticulationCache::jointForce.
eLINK_VELOCITY = (1 << 4), //!< The link velocities, see PxArticulationCache::linkVelocity. Link velocities cannot be set except for the root link velocity via PxArticulationCache::rootLinkData.
eLINK_ACCELERATION = (1 << 5), //!< The link accelerations, see PxArticulationCache::linkAcceleration.
- eROOT_TRANSFORM = (1 << 6), //!< Root link transform, see PxArticulationCache::rootLinkData.
- eROOT_VELOCITIES = (1 << 7), //!< Root link velocities (read/write) and accelerations (read), see PxArticulationCache::rootLinkData.
- eLINK_INCOMING_JOINT_FORCE = (1 << 10), //!< Link incoming joint forces, see PxArticulationCache::linkIncomingJointForce.
+ eROOT_TRANSFORM = (1 << 6), //!< The root link transform, see PxArticulationCache::rootLinkData.
+ eROOT_VELOCITIES = (1 << 7), //!< The root link velocities (read/write) and accelerations (read), see PxArticulationCache::rootLinkData.
+ eLINK_INCOMING_JOINT_FORCE = (1 << 10), //!< The link incoming joint forces, see PxArticulationCache::linkIncomingJointForce.
eJOINT_TARGET_POSITIONS = (1 << 11), //!< The joint target positions, see PxArticulationCache::jointTargetPositions.
eJOINT_TARGET_VELOCITIES = (1 << 12), //!< The joint target velocities, see PxArticulationCache::jointTargetVelocities.
+ eLINK_FORCE = (1 << 13), //!< The link forces, see PxArticulationCache::linkForce.
+ eLINK_TORQUE = (1 << 14), //!< The link torques, see PxArticulationCache::linkTorque.
eALL = (eVELOCITY | eACCELERATION | ePOSITION | eLINK_VELOCITY | eLINK_ACCELERATION | eROOT_TRANSFORM | eROOT_VELOCITIES)
};
};
diff --git a/physx/include/PxArticulationReducedCoordinate.h b/physx/include/PxArticulationReducedCoordinate.h
index a68a15158..5021b54e4 100644
--- a/physx/include/PxArticulationReducedCoordinate.h
+++ b/physx/include/PxArticulationReducedCoordinate.h
@@ -111,6 +111,8 @@ namespace physx
linkVelocity (NULL),
linkAcceleration (NULL),
linkIncomingJointForce (NULL),
+ linkForce (NULL),
+ linkTorque (NULL),
rootLinkData (NULL),
coefficientMatrix (NULL),
lambda (NULL),
@@ -261,7 +263,27 @@ namespace physx
\note The root link reports a zero spatial force.
*/
PxSpatialForce* linkIncomingJointForce;
-
+
+ /**
+ \brief Link force, i.e. an external force applied to the link's center of mass.
+
+ - N = getNbLinks().
+ - Write using PxArticulationCacheFlag::eLINK_FORCE.
+ - The indexing follows the internal link indexing, see PxArticulationLink::getLinkIndex.
+ - The force is given in world space.
+ */
+ PxVec3* linkForce;
+
+ /**
+ \brief Link torque, i.e. an external torque applied to the link.
+
+ - N = getNbLinks().
+ - Write using PxArticulationCacheFlag::eLINK_TORQUE.
+ - The indexing follows the internal link indexing, see PxArticulationLink::getLinkIndex.
+ - The torque is given in world space.
+ */
+ PxVec3* linkTorque;
+
/**
\brief Root link transform, velocities, and accelerations.
diff --git a/physx/include/PxContact.h b/physx/include/PxContact.h
index a37956d21..ba2ccb51e 100644
--- a/physx/include/PxContact.h
+++ b/physx/include/PxContact.h
@@ -733,6 +733,16 @@ class PxFrictionAnchorStreamIterator
return mFrictionPatches[mPatchIndex].anchorImpulses[mFrictionAnchorIndex];
}
+ /**
+ \brief Get the friction anchor's normal.
+ \return The friction anchor's normal.
+ */
+ PX_CUDA_CALLABLE PX_FORCE_INLINE const PxVec3& getNormal() const
+ {
+ PX_ASSERT(patchIsValid());
+ return mContactPatches[mPatchIndex].normal;
+ }
+
/**
\brief Get current patch's static friction coefficient.
\return The patch's static friction coefficient.
diff --git a/physx/include/PxSimulationEventCallback.h b/physx/include/PxSimulationEventCallback.h
index de1b6a3a3..b283bd96b 100644
--- a/physx/include/PxSimulationEventCallback.h
+++ b/physx/include/PxSimulationEventCallback.h
@@ -708,8 +708,6 @@ PX_INLINE PxU32 PxContactPair::extractFrictionAnchors(PxContactPairFrictionAncho
{
PxFrictionAnchorStreamIterator iter(contactPatches, frictionPatches, patchCount);
- const PxU32 hasImpulses = (flags & PxContactPairFlag::eINTERNAL_HAS_IMPULSES);
-
while(iter.hasNextPatch())
{
iter.nextPatch();
@@ -719,10 +717,7 @@ PX_INLINE PxU32 PxContactPair::extractFrictionAnchors(PxContactPairFrictionAncho
PxContactPairFrictionAnchor& dst = userBuffer[nbAnchors];
dst.position = iter.getPosition();
-
- dst.impulse = hasImpulses
- ? iter.getImpulse()
- : PxVec3(0.0f);
+ dst.impulse = iter.getImpulse();
++nbAnchors;
if(nbAnchors == bufferSize)
diff --git a/physx/include/PxVisualizationParameter.h b/physx/include/PxVisualizationParameter.h
index 22be2405d..f40f4b752 100644
--- a/physx/include/PxVisualizationParameter.h
+++ b/physx/include/PxVisualizationParameter.h
@@ -142,10 +142,31 @@ struct PxVisualizationParameter
*/
eCONTACT_ERROR,
+ /**
+ \brief Visualize Contact impulses. Will enable contact information.
+ */
+ eCONTACT_IMPULSE,
+
/**
\brief Visualize Contact forces. Will enable contact information.
+ \deprecated Use eCONTACT_IMPULSE instead.
+ */
+ eCONTACT_FORCE PX_DEPRECATED = eCONTACT_IMPULSE,
+
+ /**
+ \brief Visualize friction points. Will enable contact information.
+ */
+ eFRICTION_POINT,
+
+ /**
+ \brief Visualize friction normals. Will enable contact information.
+ */
+ eFRICTION_NORMAL,
+
+ /**
+ \brief Visualize friction impulses. Will enable contact information.
*/
- eCONTACT_FORCE,
+ eFRICTION_IMPULSE,
/**
\brief Visualize actor axes.
diff --git a/physx/include/extensions/PxSerialization.h b/physx/include/extensions/PxSerialization.h
index 3124f23c4..9f18daa19 100644
--- a/physx/include/extensions/PxSerialization.h
+++ b/physx/include/extensions/PxSerialization.h
@@ -41,7 +41,7 @@
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 "EEDFDB718C504480BB77F9B8DA353B60"
+#define PX_BINARY_SERIAL_VERSION "B57177A5EF424885A73E41854E472FC4"
#if !PX_DOXYGEN
diff --git a/physx/include/foundation/PxPhysicsVersion.h b/physx/include/foundation/PxPhysicsVersion.h
index e7f17427c..7f2e3f766 100644
--- a/physx/include/foundation/PxPhysicsVersion.h
+++ b/physx/include/foundation/PxPhysicsVersion.h
@@ -47,7 +47,7 @@ sometimes they are stored in a byte.
#define PX_PHYSICS_VERSION_MAJOR 5
#define PX_PHYSICS_VERSION_MINOR 4
-#define PX_PHYSICS_VERSION_BUGFIX 0
+#define PX_PHYSICS_VERSION_BUGFIX 1
/**
The constant PX_PHYSICS_VERSION is used when creating certain PhysX module objects.
diff --git a/physx/include/foundation/PxVecQuat.h b/physx/include/foundation/PxVecQuat.h
index 060febddb..032734c85 100644
--- a/physx/include/foundation/PxVecQuat.h
+++ b/physx/include/foundation/PxVecQuat.h
@@ -297,7 +297,7 @@ PX_FORCE_INLINE bool isFiniteQuatV(const QuatV q)
return isFiniteVec4V(q);
}
-#if PX_LINUX && PX_CLANG
+#if (PX_LINUX || PX_SWITCH) && PX_CLANG
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wbitwise-instead-of-logical" // bitwise intentionally chosen for performance
#endif
diff --git a/physx/snippets/compiler/cmake/CMakeLists.txt b/physx/snippets/compiler/cmake/CMakeLists.txt
index 597ea775d..60b9fde38 100644
--- a/physx/snippets/compiler/cmake/CMakeLists.txt
+++ b/physx/snippets/compiler/cmake/CMakeLists.txt
@@ -87,8 +87,8 @@ IF(NOT PUBLIC_RELEASE AND NOT PX_GENERATE_SOURCE_DISTRO)
ENDIF()
#TODO, create a propper define for whether GPU features are enabled or not!
-IF ((PUBLIC_RELEASE OR PX_GENERATE_GPU_PROJECTS) AND (NOT CMAKE_CROSSCOMPILING))
- LIST(APPEND SNIPPETS_LIST ${GPU_SNIPPET_LIST})
+IF ((PUBLIC_RELEASE OR PX_GENERATE_GPU_PROJECTS) AND (NOT CMAKE_CROSSCOMPILING OR NOT (CMAKE_GENERATOR_PLATFORM STREQUAL "NX64")))
+ LIST(APPEND SNIPPETS_LIST ${GPU_SNIPPET_LIST})
ENDIF()
SET(SNIPPETS_VEHICLE2_LIST Vehicle2DirectDrive Vehicle2FourWheelDrive Vehicle2TankDrive Vehicle2CustomSuspension Vehicle2Multithreading Vehicle2Truck Vehicle2CustomTire)
diff --git a/physx/source/compiler/cmake/PhysXExtensions.cmake b/physx/source/compiler/cmake/PhysXExtensions.cmake
index 2216e8cbe..1dc45532c 100644
--- a/physx/source/compiler/cmake/PhysXExtensions.cmake
+++ b/physx/source/compiler/cmake/PhysXExtensions.cmake
@@ -78,7 +78,7 @@ SET(PHYSX_EXTENSIONS_SOURCE
)
#TODO, create a propper define for whether GPU features are enabled or not!
-IF ((PUBLIC_RELEASE OR PX_GENERATE_GPU_PROJECTS) AND (NOT CMAKE_CROSSCOMPILING))
+IF ((PUBLIC_RELEASE OR PX_GENERATE_GPU_PROJECTS) AND (NOT CMAKE_CROSSCOMPILING OR NOT (CMAKE_GENERATOR_PLATFORM STREQUAL "NX64")))
LIST(APPEND PHYSX_EXTENSIONS_SOURCE "${LL_SOURCE_DIR}/ExtParticleExt.cpp")
LIST(APPEND PHYSX_EXTENSIONS_SOURCE "${LL_SOURCE_DIR}/ExtParticleClothCooker.cpp")
diff --git a/physx/source/lowleveldynamics/src/DyFeatherstoneArticulation.cpp b/physx/source/lowleveldynamics/src/DyFeatherstoneArticulation.cpp
index 093cc47fe..0fb3bb381 100644
--- a/physx/source/lowleveldynamics/src/DyFeatherstoneArticulation.cpp
+++ b/physx/source/lowleveldynamics/src/DyFeatherstoneArticulation.cpp
@@ -614,6 +614,8 @@ namespace Dy
+ sizeof(PxSpatialVelocity) * linkCount * 2 // link velocity, (PxArticulationCacheFlag::eLINK_VELOCITY)
// link acceleration (PxArticulationCacheFlag::eLINK_ACCELERATION)
+ sizeof(PxSpatialForce) * linkCount // link incoming joint forces (PxArticulationCacheFlag::eLINK_INCOMING_JOINT_FORCE)
+ + sizeof(PxVec3) * linkCount * 2 // link force (PxArticulationCacheFlag::eLINK_FORCE)
+ // link torque (PxArticulationCacheFlag::eLINK_TORQUE)
+ sizeof(PxArticulationRootLinkData); // root link data (PxArticulationCacheFlag::eROOT_TRANSFORM, PxArticulationCacheFlag::eROOT_VELOCITIES)
return totalSize;
@@ -665,6 +667,15 @@ namespace Dy
cache->linkIncomingJointForce = reinterpret_cast(tCache + offset);
offset += sizeof(PxSpatialForce) * linkCount;
+ // PxArticulationCacheFlag::eLINK_FORCE
+ PX_ASSERT((offset & 15) == 0);
+ cache->linkForce = reinterpret_cast(tCache + offset);
+ offset += sizeof(PxVec3) * linkCount;
+
+ // PxArticulationCacheFlag::eLINK_TORQUE
+ cache->linkTorque = reinterpret_cast(tCache + offset);
+ offset += sizeof(PxVec3) * linkCount;
+
cache->denseJacobian = reinterpret_cast(tCache + offset);
offset += sizeof(PxReal) * (6 + totalDofs) * (linkCount * 6); //size of dense jacobian assuming free floating base link.
@@ -705,6 +716,7 @@ namespace Dy
PxU32 scratchMemorySize =
sizeof(Cm::SpatialVectorF) * linkCount * 5 //motionVelocity, motionAccelerations, coriolisVectors, spatialZAVectors, externalAccels;
+ sizeof(Dy::SpatialMatrix) * linkCount //compositeSpatialInertias;
+ + sizeof(PxVec3) * linkCount * 2 //linkForce, linkTorque
+ sizeof(PxReal) * totalDofs * 7; //jointVelocity, jointAcceleration, jointForces, jointPositions, jointFrictionForces, jointTargetPositions, jointTargetVelocities
scratchMemorySize = (scratchMemorySize+15)&~15;
diff --git a/physx/source/lowleveldynamics/src/DyFeatherstoneInverseDynamic.cpp b/physx/source/lowleveldynamics/src/DyFeatherstoneInverseDynamic.cpp
index da165cf99..4351aa9df 100644
--- a/physx/source/lowleveldynamics/src/DyFeatherstoneInverseDynamic.cpp
+++ b/physx/source/lowleveldynamics/src/DyFeatherstoneInverseDynamic.cpp
@@ -360,6 +360,44 @@ namespace Dy
mGPUDirtyFlags |= ArticulationDirtyFlag::eDIRTY_JOINT_TARGET_VEL;
}
+ if (flag & PxArticulationCacheFlag::eLINK_FORCE)
+ {
+ const PxU32 linkCount = data.getLinkCount();
+ for (PxU32 i = 0; i < linkCount; ++i)
+ {
+ const PxVec3 linkForce = cache.linkForce[i];
+ localShouldWake = localShouldWake || linkForce != PxVec3(0.0f);
+ ArticulationLink& link = mArticulationData.getLink(i);
+
+ PxsBodyCore& core = *link.bodyCore;
+ data.mExternalAcceleration[i].linear = linkForce * core.inverseMass;
+ }
+ mGPUDirtyFlags |= ArticulationDirtyFlag::eDIRTY_EXT_ACCEL;
+ }
+
+ if (flag & PxArticulationCacheFlag::eLINK_TORQUE)
+ {
+ const PxU32 linkCount = data.getLinkCount();
+ for (PxU32 i = 0; i < linkCount; ++i)
+ {
+ ArticulationLink& link = mArticulationData.getLink(i);
+ PxsBodyCore& core = *link.bodyCore;
+
+ const PxQuat& q = core.body2World.q;
+ const PxVec3& linkTorque = cache.linkTorque[i];
+ const PxVec3 localLinkTorque = q.rotateInv(linkTorque);
+ localShouldWake = localShouldWake || localLinkTorque != PxVec3(0.0f);
+
+ // turn localLinkTorque into acceleration in local frame
+ const PxVec3 localAccel = core.inverseInertia.multiply(localLinkTorque);
+ // turn localAccel into world space
+ const PxVec3 worldAccel = q.rotate(localAccel);
+
+ data.mExternalAcceleration[i].angular = worldAccel;
+ }
+ mGPUDirtyFlags |= ArticulationDirtyFlag::eDIRTY_EXT_ACCEL;
+ }
+
// the updateKinematic functions rely on updated joint frames.
if (mJcalcDirty)
{
diff --git a/physx/source/physx/src/NpFactory.cpp b/physx/source/physx/src/NpFactory.cpp
index 28adff965..3dd663e88 100644
--- a/physx/source/physx/src/NpFactory.cpp
+++ b/physx/source/physx/src/NpFactory.cpp
@@ -224,7 +224,7 @@ void NpFactory::onArticulationRelease(PxArticulationReducedCoordinate* a)
NpArticulationLink* NpFactory::createNpArticulationLink(NpArticulationReducedCoordinate& root, NpArticulationLink* parent, const PxTransform& pose)
{
- NpArticulationLink* npArticulationLink;
+ NpArticulationLink* npArticulationLink;
{
PxMutex::ScopedLock lock(mArticulationLinkPoolLock);
npArticulationLink = mArticulationLinkPool.construct(pose, root, parent);
@@ -941,7 +941,6 @@ void NpFactory::addCollection(const Collection& collection)
{
NpAggregate* np = static_cast(s);
addAggregate(np, false);
-
// PT: TODO: double-check this.... is it correct?
for(PxU32 j=0;jgetCurrentSizeFast();j++)
{
@@ -949,11 +948,17 @@ void NpFactory::addCollection(const Collection& collection)
const PxType serialType1 = actor->getConcreteType();
if(serialType1==PxConcreteType::eRIGID_STATIC)
+ {
addRigidStatic(static_cast(actor), false);
+ }
else if(serialType1==PxConcreteType::eRIGID_DYNAMIC)
+ {
addRigidDynamic(static_cast(actor), false);
+ }
else if(serialType1==PxConcreteType::eARTICULATION_LINK)
- {}
+ {
+ // This is not needed as the articulation links get handled separately
+ }
else PX_ASSERT(0);
}
}
@@ -964,11 +969,11 @@ void NpFactory::addCollection(const Collection& collection)
}
else if(serialType==PxConcreteType::eARTICULATION_LINK)
{
-// NpArticulationLink* np = static_cast(s);
+ OMNI_PVD_NOTIFY_ADD(static_cast(s));
}
else if(serialType==PxConcreteType::eARTICULATION_JOINT_REDUCED_COORDINATE)
{
-// NpArticulationJoint* np = static_cast(s);
+ OMNI_PVD_NOTIFY_ADD(static_cast(s));
}
else
{
diff --git a/physx/source/physxmetadata/core/include/PxAutoGeneratedMetaDataObjects.h b/physx/source/physxmetadata/core/include/PxAutoGeneratedMetaDataObjects.h
index 33acd1ba2..7fcfde09c 100644
--- a/physx/source/physxmetadata/core/include/PxAutoGeneratedMetaDataObjects.h
+++ b/physx/source/physxmetadata/core/include/PxAutoGeneratedMetaDataObjects.h
@@ -1220,6 +1220,8 @@ template<> struct PxEnumTraits< physx::PxArticulationFlag::Enum > { PxEnumTraits
{ "eLINK_INCOMING_JOINT_FORCE", static_cast( physx::PxArticulationCacheFlag::eLINK_INCOMING_JOINT_FORCE ) },
{ "eJOINT_TARGET_POSITIONS", static_cast( physx::PxArticulationCacheFlag::eJOINT_TARGET_POSITIONS ) },
{ "eJOINT_TARGET_VELOCITIES", static_cast( physx::PxArticulationCacheFlag::eJOINT_TARGET_VELOCITIES ) },
+ { "eLINK_FORCE", static_cast( physx::PxArticulationCacheFlag::eLINK_FORCE ) },
+ { "eLINK_TORQUE", static_cast( physx::PxArticulationCacheFlag::eLINK_TORQUE ) },
{ "eALL", static_cast( physx::PxArticulationCacheFlag::eALL ) },
{ NULL, 0 }
};
@@ -2471,7 +2473,11 @@ template<> struct PxEnumTraits< physx::PxSolverType::Enum > { PxEnumTraits() : N
{ "eCONTACT_POINT", static_cast( physx::PxVisualizationParameter::eCONTACT_POINT ) },
{ "eCONTACT_NORMAL", static_cast( physx::PxVisualizationParameter::eCONTACT_NORMAL ) },
{ "eCONTACT_ERROR", static_cast( physx::PxVisualizationParameter::eCONTACT_ERROR ) },
+ { "eCONTACT_IMPULSE", static_cast( physx::PxVisualizationParameter::eCONTACT_IMPULSE ) },
{ "eCONTACT_FORCE", static_cast( physx::PxVisualizationParameter::eCONTACT_FORCE ) },
+ { "eFRICTION_POINT", static_cast( physx::PxVisualizationParameter::eFRICTION_POINT ) },
+ { "eFRICTION_NORMAL", static_cast( physx::PxVisualizationParameter::eFRICTION_NORMAL ) },
+ { "eFRICTION_IMPULSE", static_cast( physx::PxVisualizationParameter::eFRICTION_IMPULSE ) },
{ "eACTOR_AXES", static_cast( physx::PxVisualizationParameter::eACTOR_AXES ) },
{ "eCOLLISION_AABBS", static_cast( physx::PxVisualizationParameter::eCOLLISION_AABBS ) },
{ "eCOLLISION_SHAPES", static_cast( physx::PxVisualizationParameter::eCOLLISION_SHAPES ) },
diff --git a/physx/source/simulationcontroller/include/ScArticulationJointCore.h b/physx/source/simulationcontroller/include/ScArticulationJointCore.h
index 1455fa6c3..74e3abcea 100644
--- a/physx/source/simulationcontroller/include/ScArticulationJointCore.h
+++ b/physx/source/simulationcontroller/include/ScArticulationJointCore.h
@@ -90,6 +90,9 @@ namespace Sc
void setJointVelocity(PxArticulationAxis::Enum axis, const PxReal jointVel);
PxReal getJointVelocity(PxArticulationAxis::Enum axis) const;
+ void setMaxJointVelocity(PxReal maxJointV);
+ PX_FORCE_INLINE PxReal getMaxJointVelocity() const { return mCore.maxJointVelocity; }
+
// PT: TODO: don't we need to set ArticulationJointCoreDirtyFlag::eMOTION here?
PX_FORCE_INLINE void setMotion(PxArticulationAxis::Enum axis, PxArticulationMotion::Enum motion) { mCore.motion[axis] = PxU8(motion); }
PX_FORCE_INLINE PxArticulationMotion::Enum getMotion(PxArticulationAxis::Enum axis) const { return PxArticulationMotion::Enum(mCore.motion[axis]); }
@@ -97,12 +100,9 @@ namespace Sc
PX_FORCE_INLINE void setJointType(PxArticulationJointType::Enum type) { mCore.initJointType(type); }
PX_FORCE_INLINE PxArticulationJointType::Enum getJointType() const { return PxArticulationJointType::Enum(mCore.jointType); }
- PX_FORCE_INLINE void setFrictionCoefficient(const PxReal coefficient) { mCore.initFrictionCoefficient(coefficient); }
+ void setFrictionCoefficient(const PxReal coefficient);
PX_FORCE_INLINE PxReal getFrictionCoefficient() const { return mCore.frictionCoefficient; }
- PX_FORCE_INLINE void setMaxJointVelocity(const PxReal maxJointV) { mCore.initMaxJointVelocity(maxJointV); }
- PX_FORCE_INLINE PxReal getMaxJointVelocity() const { return mCore.maxJointVelocity; }
-
PX_FORCE_INLINE ArticulationJointSim* getSim() const { return mSim; }
PX_FORCE_INLINE void setSim(ArticulationJointSim* sim)
{
diff --git a/physx/source/simulationcontroller/include/ScScene.h b/physx/source/simulationcontroller/include/ScScene.h
index 19dc5862b..54e8a43e3 100644
--- a/physx/source/simulationcontroller/include/ScScene.h
+++ b/physx/source/simulationcontroller/include/ScScene.h
@@ -431,6 +431,7 @@ namespace Sc
PxU32 getDefaultContactReportStreamBufferSize() const;
void visualizeStartStep();
+ void visualizeContacts();
// PX_ENABLE_SIM_STATS
void getStats(PxSimulationStatistics& stats) const;
diff --git a/physx/source/simulationcontroller/src/ScArticulationJointCore.cpp b/physx/source/simulationcontroller/src/ScArticulationJointCore.cpp
index 0fc70b9e8..0fd81f4c9 100644
--- a/physx/source/simulationcontroller/src/ScArticulationJointCore.cpp
+++ b/physx/source/simulationcontroller/src/ScArticulationJointCore.cpp
@@ -276,3 +276,17 @@ void Sc::ArticulationJointCore::setDrive(PxArticulationAxis::Enum axis, const Px
setSimDirty();
}
+
+void Sc::ArticulationJointCore::setFrictionCoefficient(PxReal frictionCoefficient)
+{
+ mCore.initFrictionCoefficient(frictionCoefficient);
+
+ setSimDirty();
+}
+
+void Sc::ArticulationJointCore::setMaxJointVelocity(PxReal maxJointV)
+{
+ mCore.initMaxJointVelocity(maxJointV);
+
+ setSimDirty();
+}
diff --git a/physx/source/simulationcontroller/src/ScFiltering.cpp b/physx/source/simulationcontroller/src/ScFiltering.cpp
index d95ff61ad..6b3012fcd 100644
--- a/physx/source/simulationcontroller/src/ScFiltering.cpp
+++ b/physx/source/simulationcontroller/src/ScFiltering.cpp
@@ -492,6 +492,9 @@ static PX_FORCE_INLINE bool testShapeSimCorePointers(const ShapeSimBase* s0, con
// GW: further defensive coding added for OM-111249 / PX-4478.
// This is only a temporary / immediate solution to mitigate crashes
// Still need to root-cause what is causing null pointers here
+ //
+ // AD: TODO what are we doing about this now that there is a fix? Can we "deprecate" this test?
+ //
// ### DEFENSIVE
if(!isValid0 || !isValid1)
return outputError(__LINE__, "NPhaseCore::runOverlapFilters: found null PxsShapeCore pointers!");
diff --git a/physx/source/simulationcontroller/src/ScPipeline.cpp b/physx/source/simulationcontroller/src/ScPipeline.cpp
index 53bb31887..12cc87b11 100644
--- a/physx/source/simulationcontroller/src/ScPipeline.cpp
+++ b/physx/source/simulationcontroller/src/ScPipeline.cpp
@@ -1492,6 +1492,7 @@ void Sc::Scene::setEdgesConnected(PxBaseTask*)
ShapeInteraction* si = getSI(mTouchFoundEvents[i]);
// jcarius: defensive coding for OM-99507. If this assert hits, you maybe hit the same issue, please report!
+ // ### DEFENSIVE
if(si == NULL || si->getEdgeIndex() == IG_INVALID_EDGE)
{
outputError(__LINE__, "Sc::Scene::setEdgesConnected: adding an invalid edge. Skipping.");
@@ -1866,6 +1867,16 @@ void Sc::Scene::processNarrowPhaseLostTouchEventsIslands(PxBaseTask*)
for(PxU32 i=0; i getEdgeIndex() == IG_INVALID_EDGE)
+ {
+ outputError(__LINE__, "Sc::Scene::setEdgeDisconnected: removing an invalid edge. Skipping.");
+ PX_ALWAYS_ASSERT();
+ continue;
+ }
+
mSimpleIslandManager->setEdgeDisconnected(si->getEdgeIndex());
}
}
@@ -1891,6 +1902,16 @@ void Sc::Scene::processNarrowPhaseLostTouchEvents(PxBaseTask*)
for(PxU32 i=0; igetEdgeIndex() == IG_INVALID_EDGE)
+ {
+ outputError(__LINE__, "Sc::Scene::processNarrowPhaseLostTouchEvents: processing an invalid edge. Skipping.");
+ PX_ALWAYS_ASSERT();
+ continue;
+ }
+
PX_ASSERT(si);
if(si->managerLostTouch(0, true, outputs) && !si->readFlag(ShapeInteraction::CONTACTS_RESPONSE_DISABLED))
addToLostTouchList(si->getShape0().getActor(), si->getShape1().getActor());
@@ -2433,6 +2454,10 @@ void Sc::Scene::finalizationPhase(PxBaseTask* /*continuation*/)
// AD: WIP, will be gone once we removed the warm-start with sim step.
if (mPublicFlags & PxSceneFlag::eENABLE_DIRECT_GPU_API)
setDirectGPUAPIInitialized();
+
+ // VR: do this at finalizationPhase when all contact and
+ // friction impulses and CCD contacts are already computed
+ visualizeContacts();
}
void Sc::Scene::collectSolverResidual()
diff --git a/physx/source/simulationcontroller/src/ScShapeInteraction.cpp b/physx/source/simulationcontroller/src/ScShapeInteraction.cpp
index 5dc551c09..d419a87e9 100644
--- a/physx/source/simulationcontroller/src/ScShapeInteraction.cpp
+++ b/physx/source/simulationcontroller/src/ScShapeInteraction.cpp
@@ -571,6 +571,15 @@ void Sc::ShapeInteraction::sendLostTouchReport(bool shapeVolumeRemoved, PxU32 cc
PxU32 Sc::ShapeInteraction::getContactPointData(const void*& contactPatches, const void*& contactPoints, PxU32& contactDataSize, PxU32& contactPointCount, PxU32& numPatches, const PxReal*& impulses, PxU32 startOffset,
PxsContactManagerOutputIterator& outputs)
+{
+ const void* frictionPatches;
+ return getContactPointData(contactPatches, contactPoints, contactDataSize,
+ contactPointCount, numPatches, impulses, startOffset,
+ outputs, frictionPatches);
+}
+
+PxU32 Sc::ShapeInteraction::getContactPointData(const void*& contactPatches, const void*& contactPoints, PxU32& contactDataSize, PxU32& contactPointCount, PxU32& numPatches, const PxReal*& impulses, PxU32 startOffset,
+ PxsContactManagerOutputIterator& outputs, const void*& frictionPatches)
{
// Process LL generated contacts
if(mManager != NULL)
@@ -608,6 +617,7 @@ PxU32 Sc::ShapeInteraction::getContactPointData(const void*& contactPatches, con
contactPointCount = output->nbContacts;
numPatches = output->nbPatches;
impulses = output->contactForces;
+ frictionPatches = output->frictionPatches;
if(!ccdContactStream)
return startOffset;
@@ -630,6 +640,7 @@ PxU32 Sc::ShapeInteraction::getContactPointData(const void*& contactPatches, con
contactPointCount = 1;
numPatches = 1;
impulses = reinterpret_cast(stream + ((streamSize + 0xf) & 0xfffffff0));
+ frictionPatches = NULL;
if(!ccdContactStream->nextStream)
return startOffset;
@@ -653,6 +664,7 @@ PxU32 Sc::ShapeInteraction::getContactPointData(const void*& contactPatches, con
contactPointCount = 0;
numPatches = 0;
impulses = NULL;
+ frictionPatches = NULL;
return startOffset;
}
@@ -776,7 +788,10 @@ PX_FORCE_INLINE void Sc::ShapeInteraction::updateFlags(const Sc::Scene& scene, c
scene.getVisualizationParameter(PxVisualizationParameter::eCONTACT_POINT) ||
scene.getVisualizationParameter(PxVisualizationParameter::eCONTACT_NORMAL) ||
scene.getVisualizationParameter(PxVisualizationParameter::eCONTACT_ERROR) ||
- scene.getVisualizationParameter(PxVisualizationParameter::eCONTACT_FORCE)) );
+ scene.getVisualizationParameter(PxVisualizationParameter::eCONTACT_IMPULSE)) ||
+ scene.getVisualizationParameter(PxVisualizationParameter::eFRICTION_POINT) ||
+ scene.getVisualizationParameter(PxVisualizationParameter::eFRICTION_NORMAL) ||
+ scene.getVisualizationParameter(PxVisualizationParameter::eFRICTION_IMPULSE) );
}
PX_INLINE PxReal ScGetRestOffset(const Sc::ShapeSimBase& shapeSim)
diff --git a/physx/source/simulationcontroller/src/ScShapeInteraction.h b/physx/source/simulationcontroller/src/ScShapeInteraction.h
index 967cafd4f..c6ededb9b 100644
--- a/physx/source/simulationcontroller/src/ScShapeInteraction.h
+++ b/physx/source/simulationcontroller/src/ScShapeInteraction.h
@@ -97,10 +97,11 @@ namespace Sc
PxsContactManagerOutputIterator& outputs, ContactReportAllocationManager* alloc = NULL); // ccdPass is 0 for discrete collision and then 1,2,... for the CCD passes
void visualize( PxRenderOutput&, PxsContactManagerOutputIterator&,
- float scale, float param_contactForce, float param_contactNormal, float param_contactError, float param_contactPoint
- );
+ float scale, float contactImpulse, float contactNormal, float contactError, float contactPoint,
+ float frictionImpulse, float frictionNormal, float frictionPoint);
PxU32 getContactPointData(const void*& contactPatches, const void*& contactPoints, PxU32& contactDataSize, PxU32& contactPointCount, PxU32& patchCount, const PxReal*& impulses, PxU32 startOffset, PxsContactManagerOutputIterator& outputs);
+ PxU32 getContactPointData(const void*& contactPatches, const void*& contactPoints, PxU32& contactDataSize, PxU32& contactPointCount, PxU32& patchCount, const PxReal*& impulses, PxU32 startOffset, PxsContactManagerOutputIterator& outputs, const void*& frictionPatches);
bool managerLostTouch(PxU32 ccdPass, bool adjustCounters, PxsContactManagerOutputIterator& outputs);
void managerNewTouch(PxU32 ccdPass, bool adjustCounters, PxsContactManagerOutputIterator& outputs);
diff --git a/physx/source/simulationcontroller/src/ScVisualize.cpp b/physx/source/simulationcontroller/src/ScVisualize.cpp
index cd215ca85..1ad4e9bb9 100644
--- a/physx/source/simulationcontroller/src/ScVisualize.cpp
+++ b/physx/source/simulationcontroller/src/ScVisualize.cpp
@@ -56,7 +56,8 @@ static void visualize(const ConstraintSim& sim, Cm::ConstraintImmediateVisualize
}
void Sc::ShapeInteraction::visualize(PxRenderOutput& out, PxsContactManagerOutputIterator& outputs,
- float scale, float param_contactForce, float param_contactNormal, float param_contactError, float param_contactPoint)
+ float scale, float contactImpulse, float contactNormal, float contactError, float contactPoint,
+ float frictionImpulse, float frictionNormal, float frictionPoint)
{
if(mManager) // sleeping pairs have no contact points -> do not visualize
{
@@ -74,12 +75,14 @@ void Sc::ShapeInteraction::visualize(PxRenderOutput& out, PxsContactManagerOutpu
PxU32 contactPointCount;
PxU32 contactPatchCount;
const PxReal* impulses;
+ const void* frictionPatches;
offset = nextOffset;
- nextOffset = getContactPointData(contactPatches, contactPoints, contactDataSize, contactPointCount, contactPatchCount, impulses, offset, outputs);
+ nextOffset = getContactPointData(contactPatches, contactPoints, contactDataSize, contactPointCount, contactPatchCount, impulses, offset, outputs, frictionPatches);
const PxU32* faceIndices = reinterpret_cast(impulses + contactPointCount);
PxContactStreamIterator iter(reinterpret_cast(contactPatches), reinterpret_cast(contactPoints), faceIndices, contactPatchCount, contactPointCount);
+ PxFrictionAnchorStreamIterator fricIter(reinterpret_cast(contactPatches), reinterpret_cast(frictionPatches), contactPatchCount);
PxU32 i = 0;
while(iter.hasNextPatch())
@@ -89,23 +92,23 @@ void Sc::ShapeInteraction::visualize(PxRenderOutput& out, PxsContactManagerOutpu
{
iter.nextContact();
- if((param_contactForce != 0.0f) && impulses)
+ if((contactImpulse != 0.0f) && impulses)
{
out << PxU32(PxDebugColor::eARGB_RED);
- out.outputSegment(iter.getContactPoint(), iter.getContactPoint() + iter.getContactNormal() * (scale * param_contactForce * impulses[i]));
+ out.outputSegment(iter.getContactPoint(), iter.getContactPoint() + iter.getContactNormal() * (scale * contactImpulse * impulses[i]));
}
- else if(param_contactNormal != 0.0f)
+ else if(contactNormal != 0.0f)
{
out << PxU32(PxDebugColor::eARGB_BLUE);
- out.outputSegment(iter.getContactPoint(), iter.getContactPoint() + iter.getContactNormal() * (scale * param_contactNormal));
+ out.outputSegment(iter.getContactPoint(), iter.getContactPoint() + iter.getContactNormal() * (scale * contactNormal));
}
- else if(param_contactError != 0.0f)
+ else if(contactError != 0.0f)
{
out << PxU32(PxDebugColor::eARGB_YELLOW);
- out.outputSegment(iter.getContactPoint(), iter.getContactPoint() + iter.getContactNormal() * PxAbs(scale * param_contactError * PxMin(0.f, iter.getSeparation())));
+ out.outputSegment(iter.getContactPoint(), iter.getContactPoint() + iter.getContactNormal() * PxAbs(scale * contactError * PxMin(0.f, iter.getSeparation())));
}
- if(param_contactPoint != 0.0f)
+ if(contactPoint != 0.0f)
{
const PxReal s = scale * 0.1f;
const PxVec3& point = iter.getContactPoint();
@@ -120,6 +123,37 @@ void Sc::ShapeInteraction::visualize(PxRenderOutput& out, PxsContactManagerOutpu
}
i++;
}
+
+ if (fricIter.hasNextPatch())
+ {
+ fricIter.nextPatch();
+ while (fricIter.hasNextFrictionAnchor())
+ {
+ fricIter.nextFrictionAnchor();
+
+ if (frictionImpulse != 0.0f)
+ {
+ out << PxU32(PxDebugColor::eARGB_DARKRED);
+ out.outputSegment(fricIter.getPosition(), fricIter.getPosition() + fricIter.getImpulse() * (scale * frictionImpulse));
+ }
+ else if (frictionNormal != 0.0f)
+ {
+ out << PxU32(PxDebugColor::eARGB_BLUE);
+ out.outputSegment(fricIter.getPosition(), fricIter.getPosition() + fricIter.getNormal() * (scale * frictionNormal));
+ }
+
+ if (frictionPoint != 0.0f)
+ {
+ const PxReal s = scale * 0.1f;
+ const PxVec3& p = fricIter.getPosition();
+
+ out << PxU32(PxDebugColor::eARGB_DARKRED);
+ out.outputSegment(p + PxVec3(-s, 0, 0), p + PxVec3(s, 0, 0));
+ out.outputSegment(p + PxVec3(0, -s, 0), p + PxVec3(0, s, 0));
+ out.outputSegment(p + PxVec3(0, 0, -s), p + PxVec3(0, 0, s));
+ }
+ }
+ }
}
} while (nextOffset != offset);
}
@@ -138,7 +172,9 @@ void Sc::Scene::visualizeStartStep()
// Update SIPs if visualization is enabled
if( getVisualizationParameter(PxVisualizationParameter::eCONTACT_POINT) || getVisualizationParameter(PxVisualizationParameter::eCONTACT_NORMAL) ||
- getVisualizationParameter(PxVisualizationParameter::eCONTACT_ERROR) || getVisualizationParameter(PxVisualizationParameter::eCONTACT_FORCE))
+ getVisualizationParameter(PxVisualizationParameter::eCONTACT_ERROR) || getVisualizationParameter(PxVisualizationParameter::eCONTACT_IMPULSE) ||
+ getVisualizationParameter(PxVisualizationParameter::eFRICTION_POINT) || getVisualizationParameter(PxVisualizationParameter::eFRICTION_NORMAL) ||
+ getVisualizationParameter(PxVisualizationParameter::eFRICTION_IMPULSE))
mInternalFlags |= SceneInternalFlag::eSCENE_SIP_STATES_DIRTY_VISUALIZATION;
}
@@ -181,15 +217,39 @@ void Sc::Scene::visualizeStartStep()
}
}
}
+#else
+ PX_CATCH_UNDEFINED_ENABLE_DEBUG_VISUALIZATION
+#endif
+}
+
+// Render contacts at the simulation frame end
+void Sc::Scene::visualizeContacts()
+{
+ PX_PROFILE_ZONE("Sim.visualizeContacts", mContextId);
+
+#if PX_ENABLE_DEBUG_VISUALIZATION
+ const PxReal scale = getVisualizationScale();
+ if (scale == 0.0f)
+ {
+ // make sure visualization inside simulate was skipped
+ PX_ASSERT(getRenderBuffer().empty());
+ return; // early out if visualization scale is 0
+ }
+
+ PxRenderOutput out(getRenderBuffer());
{
// PT: put common reads here to avoid doing them for each interaction
- const PxReal param_contactForce = getVisualizationParameter(PxVisualizationParameter::eCONTACT_FORCE);
- const PxReal param_contactNormal = getVisualizationParameter(PxVisualizationParameter::eCONTACT_NORMAL);
- const PxReal param_contactError = getVisualizationParameter(PxVisualizationParameter::eCONTACT_ERROR);
- const PxReal param_contactPoint = getVisualizationParameter(PxVisualizationParameter::eCONTACT_POINT);
+ const PxReal contactImpulse = getVisualizationParameter(PxVisualizationParameter::eCONTACT_IMPULSE);
+ const PxReal contactNormal = getVisualizationParameter(PxVisualizationParameter::eCONTACT_NORMAL);
+ const PxReal contactError = getVisualizationParameter(PxVisualizationParameter::eCONTACT_ERROR);
+ const PxReal contactPoint = getVisualizationParameter(PxVisualizationParameter::eCONTACT_POINT);
+ const PxReal frictionImpulse = getVisualizationParameter(PxVisualizationParameter::eFRICTION_IMPULSE);
+ const PxReal frictionNormal = getVisualizationParameter(PxVisualizationParameter::eFRICTION_NORMAL);
+ const PxReal frictionPoint = getVisualizationParameter(PxVisualizationParameter::eFRICTION_POINT);
- if(param_contactForce!=0.0f || param_contactNormal!=0.0f || param_contactError!=0.0f || param_contactPoint!=0.0f)
+ if(contactImpulse !=0.0f || contactNormal!=0.0f || contactError!=0.0f || contactPoint!=0.0f ||
+ frictionImpulse != 0.0f || frictionNormal != 0.0f || frictionPoint != 0.0f)
{
PxsContactManagerOutputIterator outputs = mLLContext->getNphaseImplementationContext()->getContactManagerOutputs();
@@ -197,7 +257,8 @@ void Sc::Scene::visualizeStartStep()
PxU32 nbActiveInteractions = getNbActiveInteractions(InteractionType::eOVERLAP);
while(nbActiveInteractions--)
static_cast(*interactions++)->visualize( out, outputs,
- scale, param_contactForce, param_contactNormal, param_contactError, param_contactPoint);
+ scale, contactImpulse, contactNormal, contactError, contactPoint,
+ frictionImpulse, frictionNormal, frictionPoint);
}
}
#else
diff --git a/physx/version.txt b/physx/version.txt
index f0528a961..6d3e30c71 100644
--- a/physx/version.txt
+++ b/physx/version.txt
@@ -1 +1 @@
-5.4.0.05ff005f
\ No newline at end of file
+5.4.1.82786122
\ No newline at end of file