Giter Club home page Giter Club logo

physx's Introduction

NVIDIA PhysX

Copyright (c) 2008-2023 NVIDIA Corporation. All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  • Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  • Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  • Neither the name of 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.

Introduction

Welcome to the NVIDIA PhysX source code repository.

This repository contains source releases of the PhysX, Flow, and Blast SDKs used in NVIDIA Omniverse.

Documentation

The user guide and API documentation are available on GitHub Pages. Please create an Issue if you find a documentation issue.

Instructions

Please see instructions specific to each of the libraries in the respective subfolder.

Community-Maintained Build Configuration Fork

Please see the O3DE Fork for community-maintained additional build configurations.

Support

  • Please use GitHub Discussions for questions and comments.
  • GitHub Issues should only be used for bug reports or documentation issues.
  • You can also ask questions in the NVIDIA Omniverse #physics Discord Channel.

physx's People

Contributors

amoravanszky avatar areidmeyer avatar ayoub-belarbi avatar gavanw avatar nvidia-bgaldrikian avatar preist-nvidia avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

physx's Issues

Unable to create D6 joint from separate library when statically linking PhysX

I just stumbled over this issue while testing my Unreal Engine integration. It seems that if you use the static libraries for PhysX, and attempt to use PxD6JointCreate in a different dll than the one that initialized PhysX, it will crash because FdFoundation::mInstance is null in that dll when trying to allocate the joint. The PxPhysics passed into PxD6JointCreate could be used to find the correct foundation, but it seems to be ignored.

In my case the fix is simple - just use the dynamic library instead for modular builds - but I saw other fixes in the changelog for this exact configuration with multiple dlls using static PhysX so I thought I should bring it up here.

postFilter() not work properly in PxSceneQueryExt::overlapMultiple()

Library and Version

PhysX v5.1.2

Operating System

Example: Windows 10 20H2

Steps to Trigger Behavior

  1. Derive PxQueryFilterCallback::postFilter(const PxFilterData& filterData, const PxQueryHit& hit, const PxShape* shape, const PxRigidActor* actor), return PxQueryHitType::eNONE for unexpected actors.
  2. Raise flag: xQueryFlag::ePOSTFILTER
  3. Call PxSceneQueryExt::overlapMultiple(*m_pScene, geometry, pose, hitBuffer, bufferSize, filterData, filterCall);

Code Snippet to Reproduce Behavior


PxQueryHitType::Enum SphericalConePostFilter::postFilter(const PxFilterData& filterData, const PxQueryHit& hit,
    const PxShape* shape, const PxRigidActor* actor)
{
    PX_UNUSED(filterData);
    PX_UNUSED(hit);
    const PxGeometry& testGeom = shape->getGeometry();
    PxTransform actorGlbPse = actor->getGlobalPose();
    PxTransform geometryGlobalTm = actorGlbPse.transform(shape->getLocalPose());

    DefSphericalCone* cone = new DefSphericalCone(m_openAngle, m_radius, m_margin);

    switch (int(testGeom.getType()))
    {
    case PxGeometryType::eSPHERE:
    case PxGeometryType::eCAPSULE:
    case PxGeometryType::eBOX:
    case PxGeometryType::eCONVEXMESH:
    {
        PxGjkQueryExt::ConvexGeomSupport geomSupport(testGeom);

        if (PxGjkQuery::overlap((*cone), geomSupport, m_globalPose, geometryGlobalTm))
        {
            delete cone;
            return PxQueryHitType::eTOUCH;
        }
        break;
    }
    default:
        NX_ASSERT(false);
        break;
    }

    delete cone;
    return PxQueryHitType::eNONE;
}

...



 PxQueryFilterData filterData;
filterData.data = filter;
filterData.flags = (PxQueryFlag::PxQueryFlag::eSTATIC | PxQueryFlag::eDYNAMIC | PxQueryFlag::ePOSTFILTER | PxQueryFlag::eNO_BLOCK);

...

m_hitCount = PxSceneQueryExt::overlapMultiple(*m_pScene, geometry, pose, hitBuffer, bufferSize, filterData, filterCall);

Expected Behavior

SphericalConePostFilter() is the derived class for PxQueryFilterCallback() so since I return PxQueryHitType::eNONE in postFilter(), the overlap query overlapMultiple() should ignore it and return 0.

Actual Behavior

overlapMultiple() still return 1, even the postFilter() return PxQueryHitType::eNONE.

Assert removing aggregate with static filter hint set that overlaps other static aggregates and shapes

Hi, I've just fixed this bug so I thought you might want to take the fix. Persistent pair is only created conditionally in AABBManager::processBPCreatedPair based on their filter hints, however, AABBManager::processBPDeletedPair
expects a pair to always exist in the map, and thus causes the assert.

There is probably a better way that skips searching the map entirely based on the filter hints. So I won't create a PR with my bodge.
brickadia@204b513

Kinematic Target is applied one frame delayed

PxRigidDynamic->setKinematicTarget applies the target transform one frame delayed.

Reproduction:
Create a Kinematic Body at position 0,0,0 and enable visualizations.
Call SetKinematicTarget with position 1,0,0 and run the simulation.
Observe the the debug visualization. It will show that the body for this simulation frame is still at 0,0,0.
Only if you advance the simulation again, the body will move to 1,0,0.

After looking through the source it may happen because of the below reasoning in the comment:
File: ScBodySim.cpp
void BodySim::calculateKinematicVelocity(PxReal oneOverDt) We have to do this like so in a delayed way, because when the user sets the target pos the dt is not yet known.

As a static physics deltatime is used in many games, a solution would be to add a flag
to Kinematic Bodies, which would force the velocity and position update when calling setKinematicTarget()
by using the previous or a given deltatime.

Different integration behavior of eLOCK_ANGULAR and eLOCK_LINEAR flags

Library and Version

Example: PhysX v5.1.2

Operating System

Windows 10

Steps to Trigger Behavior

  1. Lock all axes of dynamic object with
setRigidDynamicLockFlags(PxRigidDynamicLockFlag::eLOCK_LINEAR_X | PxRigidDynamicLockFlag::eLOCK_LINEAR_Y |
                         PxRigidDynamicLockFlag::eLOCK_LINEAR_Z | PxRigidDynamicLockFlag::eLOCK_ANGULAR_X | 
                         PxRigidDynamicLockFlag::eLOCK_ANGULAR_Y | PxRigidDynamicLockFlag::eLOCK_ANGULAR_Z)
  1. set non-zero linear and angular velocity for object

Code Snippet to Reproduce Behavior

PxReal halfExt = 2.0f;
PxRigidDynamic* body = gPhysics->createRigidDynamic(PxTransform(PxVec3(0.0f, halfExt, 0.0f)));
PxShape* shape = gPhysics->createShape(PxBoxGeometry(halfExt, halfExt, halfExt), *gMaterial);
body->attachShape(*shape);
shape->release();
PxRigidBodyExt::updateMassAndInertia(*body, 10.0f);
gScene->addActor(*body);

body->setRigidDynamicLockFlags(PxRigidDynamicLockFlag::eLOCK_LINEAR_X | PxRigidDynamicLockFlag::eLOCK_LINEAR_Y |
                               PxRigidDynamicLockFlag::eLOCK_LINEAR_Z | PxRigidDynamicLockFlag::eLOCK_ANGULAR_X | 
                               PxRigidDynamicLockFlag::eLOCK_ANGULAR_Y | PxRigidDynamicLockFlag::eLOCK_ANGULAR_Z);
body->setLinearVelocity(PxVec3(0.0f, 1.0f, 0.0f));
body->setAngularVelocity(PxVec3(0.0f, PxPiDivFour, 0.0f));
body->setLinearDamping(0.0f);
body->setAngularDamping(0.0f);
body->setActorFlags(PxActorFlag::eDISABLE_GRAVITY);

Expected Behavior

Body is not moving and rotating or body is moving and rotating

Actual Behavior

Body is moving but not rotating.

Possible cause

In code block

if (lockFlags & PxRigidDynamicLockFlag::eLOCK_LINEAR_X)
data.linearVelocity.x = 0.f;
if (lockFlags & PxRigidDynamicLockFlag::eLOCK_LINEAR_Y)
data.linearVelocity.y = 0.f;
if (lockFlags & PxRigidDynamicLockFlag::eLOCK_LINEAR_Z)
data.linearVelocity.z = 0.f;
possibly should be used lin variable instead of data.linearVelocity.

Library name on Android build

I have managed to build Physx libraries for Android (latest main branch and based on O3DE). I managed to build Android versions under Windows and Linux and for armebi-v7a, arm64-v8a, x86 and x86_64 too. When I build everything under Windows the libs names contains a _64 for 64 bit builds and _32 for 32 bit builds. On Linux all libs on all archs does have _32 in it's file name. I didn't found in the cmake structure where the name is generated.

Where is the place to modify the cmake files to have the same output names generated as on windows?

Contact data race in MT

Hello,
It seems that the task of creating new contacts does is not finished before the task of merging contacts begins.
In the debug version it is hard to catch.

Library and Version

PhysX v5.1.2
PhysX v5.1.3

Operating System

Windows 10
Windows 11

Steps to Trigger Behavior

  1. Patch for debug contact outputs.
    0001-contact-error.patch

Example:

D:\_github\PhysX\physx\source\simulationcontroller\src\ScScene.cpp (4718) : internal error : nbContacts = 128
D:\_github\PhysX\physx\source\simulationcontroller\src\ScScene.cpp (4758) : internal error : contactNormal = 0.1016 -0.1016 0.1016
D:\_github\PhysX\physx\source\simulationcontroller\src\ScScene.cpp (4727) : internal error : materialIndex0 = 16576
D:\_github\PhysX\physx\source\simulationcontroller\src\ScScene.cpp (4734) : internal error : materialIndex1 = 14453
  1. Patch for threads concurrency debugging.
    0002-threads-error.patch

flow build.sh is hard-coded with behaviors that will never work on macos

Library and Version

PhysX ToT (main branch)

Operating System

macOS 22.1.0 ARM

Steps to Trigger Behavior

  1. cd flow
  2. ./build.sh

Code Snippet to Reproduce Behavior

#! /bin/bash

./generate_projects.sh

cd _compiler/gmake2

make config=debug_x86_64
make config=release_x86_64

cd ../..

Expected Behavior

A build script that does not hard-code x86_64 or assume that gmake2 is already built (the existing build.sh appears to work for only one Linux target).

Actual Behavior

./generate_projects.sh: line 3: ./external/premake/linux64/premake5: cannot execute binary file
./build.sh: line 5: cd: _compiler/gmake2: No such file or directory
make: *** No targets specified and no makefile found. Stop.
make: *** No targets specified and no makefile found. Stop.

Contact generated despite absolute seperation value higher than contact offset

Library and Version

release/104.2

Operating System

Windows 10

Description

For Capsule-Mesh contact generation, contacts can be generated whose seperation value is higher than the contact offset.
In some scenarios (image below) with relatively thin objects this can lead to contacts being generated on the opposite side of the colliding objects.

image
(Note that the image is from the old PhysX 4.1 PVD, since that is where the bug was initially discovered. The same code however is used in PhysX 4.1 and 5.0)

Proposed fix

See pull request #157
The contacOffset check compares against the t/distance value of intersectRayTriangle.
This value can however be negative, so the comparison t < radius + contactDistance can be true despite the absolute value of t being higher than radius + contactDistance

Compile error with Ubuntu 20.04 and g++11/12, but works with clang 14

Library and Version

PhysX v5.1.0 (release/104.0)

Operating System

  • OS: Ubuntu 20.04
  • Compiler: g++ 11, clang 14
  • C++ version: C++17

Steps to Trigger Behavior

  1. Compile PhysX target using clang 14 - compilation succeeds
  2. Compile PhysX target using g++ 11 - error when building PxAutoGeneratedMetaDataObjects.cpp due to macro expansion of DEFINE_PROPERTY_TO_VALUE_STRUCT_MAP in PxMetaDataObjects.h:
physx/physx/source/physxmetadata/core/src/PxAutoGeneratedMetaDataObjects.cpp
In file included from physx/physx/source/physxmetadata/core/src/PxAutoGeneratedMetaDataObjects.cpp:40:
physx/physx/source/physxmetadata/core/include/PxMetaDataObjects.h:498:87: error: expected unqualified-id before โ€˜)โ€™ token
  498 |                 PxPropertyToValueStructMemberMap< PxPropertyInfoName::type##_##prop >() : Offset( PX_OFFSET_OF_RT( valueStruct, prop ) ) {}             \
      |                                                                                       ^
physx/physx/source/physxmetadata/core/include/PxAutoGeneratedMetaDataObjects.h:60:9: note: in expansion of macro โ€˜DEFINE_PROPERTY_TO_VALUE_STRUCT_MAPโ€™
   60 |         DEFINE_PROPERTY_TO_VALUE_STRUCT_MAP( PxPhysics, TolerancesScale, PxPhysicsGeneratedValues)

Code snippets

cmake --build . --target PhysX

Expected Behavior

g++11 should successfully compile the PhysX target

Actual Behavior

g++11 is not able to compile the PhysX target

Library Mismatch on Windows

Hi there, I've linked the .lib files to my project using cmakelists, however I git this error:
LNK2038 mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MDd_DynamicDebug' in test.main.obj
File: D:\VisualStudioProjects\test\out\build\x64-debug\PhysXExtensions_static_64.lib(ExtDefaultErrorCallback.obj)

I don't know if this is normal, but the following libraries have _static in the name, the others do not:
PhysXExtensions_static_64.lib
PhysXPvdSDK_static_64.lib
PhysXVehicle_static_64.lib
PhysXCharacterKinematic_static_64.lib

I think that is the problem. I tried setting these to False in the build preset, but there seemed to be no difference:
PX_GENERATE_STATIC_LIBRARIES
NV_USE_STATIC_WINCRT

I am using a custom preset, but it's just a copy-paste of vc16win64.xml just to change it to use vc17 so that I could build the project with Visual Studio 2022.

I've seen older issues where people had the same version, but I was unable to solve the issue with the suggested solutions in those threads.

Issue running generate_projects.sh (ubuntu)

Version: PhysX v5.1.0 on Ubuntu 22.04, using gcc

Hi there, when running generate_projects.sh I get this error:

CMake Error at /home/laptop001/PhysX/physx/snippets/compiler/cmake/linux/SnippetRender.cmake:32 (find_package):

Could not find a package configuration file provided by "OpenGL" with any of the following names:

OpenGLConfig.cmake
opengl-config.cmake

Add the installation prefix of "OpenGL" to CMAKE_PREFIX_PATH or set

"OpenGL_DIR" to a directory containing one of the above files. If "OpenGL" provides a separate development package or SDK, be sure it has been installed.

Call Stack (most recent call first):
/home/laptop001/PhysX/physx/snippets/compiler/cmake/SnippetRender.cmake:32 (include)
/home/laptop001/PhysX/physx/snippets/compiler/cmake/CMakeLists.txt:111 (INCLUDE)

I do have gl packages(Such as libgl-mesa-dev, mesa-common-dev) installed on my system, as I have successfully used them in other projects.

Using version numbers in your project names

Big name projects have quit using version numbers in there projects because it is bad practice and quite annoying to the customers to either rename all the folders to fit their custom folder naming structure or to go update every dependency location. Would be super nice if you all could adapt naming PhysxX.X.X.X to just Physx with no versions. See screen shot.
image

Precision issue in index computation in Gu::HeightField::computeCellCoordinates (PxReal to PxU32)

Library and Version

PhysX v5.1.0
Release 104.0

Issue

Hi,

There is a precision issue in the computation of the vertex index in Gu::HeightField::computeCellCoordinates.

const PxU32 vertexIndex = PxU32(PxU32(x) * (mData.nbColumns) + PxU32(z));

mData.nbColumns is of type PxReal so the index computation is done in PxReal and only then cast to PxU32. This leads to problems when x, z and nbColumns have large values (~4k x 4k).
A suggested fix is to either use mData.columns like the line below or cast mData.nbColumns directly using PxU32(mData.nbColumns).

A pull request for the same issue was submitted for PhysX 4.1 ( NVIDIAGameWorks/PhysX#574 ) but the modifications that were applied for PhysX 5.1 (the final cast to PxU32) do not fix the problem.

Building Physx with Cmake

Library and Version

Version : 5.1.3.32494398

Operating System

Windows 10

Steps to Trigger Behavior

I am trying to build physx with Cmake.

Code Snippet to Reproduce Behavior

my Cmake:

cmake_minimum_required(VERSION 3.25)
project(Physx_cmake)

set(CMAKE_CXX_STANDARD 17)

set(PHYSX_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/submodules/PhysX/physx)
set(TARGET_BUILD_PLATFORM "windows")
set(CMAKEMODULES_PATH ${PHYSX_ROOT_DIR}/source/compiler/cmake/windows/)

add_subdirectory(submodules/PhysX/physx/source/compiler/cmake/windows)

add_executable(Physx_cmake main.cpp)

target_link_libraries(Physx_cmake PhysX)

Expected Behavior

Error:

Actual Behavior

"C:\Program Files\JetBrains\CLion 2021.3.4\bin\cmake\win\x64\bin\cmake.exe" -DCMAKE_BUILD_TYPE=Debug "-DCMAKE_MAKE_PROGRAM=C:/Program Files/JetBrains/CLion 2021.3.4/bin/ninja/win/x64/ninja.exe" -G Ninja -S G:\Development\Physx_cmake -B G:\Development\Physx_cmake\cmake-build-debug
CMake Error at submodules/PhysX/physx/source/compiler/cmake/windows/CMakeLists.txt:175 (INCLUDE):
  INCLUDE could not find requested file:

    PhysXGpuExtensions.cmake


CMake Error at submodules/PhysX/physx/source/compiler/cmake/windows/CMakeLists.txt:186 (SET_PROPERTY):
  SET_PROPERTY could not find TARGET PhysX.  Perhaps it has not yet been
  created.


CMake Error at submodules/PhysX/physx/source/compiler/cmake/windows/CMakeLists.txt:187 (SET_PROPERTY):
  SET_PROPERTY could not find TARGET PhysXCharacterKinematic.  Perhaps it has
  not yet been created.


CMake Error at submodules/PhysX/physx/source/compiler/cmake/windows/CMakeLists.txt:188 (SET_PROPERTY):
  SET_PROPERTY could not find TARGET PhysXCommon.  Perhaps it has not yet
  been created.


CMake Error at submodules/PhysX/physx/source/compiler/cmake/windows/CMakeLists.txt:189 (SET_PROPERTY):
  SET_PROPERTY could not find TARGET PhysXCooking.  Perhaps it has not yet
  been created.


CMake Error at submodules/PhysX/physx/source/compiler/cmake/windows/CMakeLists.txt:190 (SET_PROPERTY):
  SET_PROPERTY could not find TARGET PhysXExtensions.  Perhaps it has not yet
  been created.


CMake Error at submodules/PhysX/physx/source/compiler/cmake/windows/CMakeLists.txt:192 (SET_PROPERTY):
  SET_PROPERTY could not find TARGET PhysXGPUExtensions.  Perhaps it has not
  yet been created.


CMake Error at submodules/PhysX/physx/source/compiler/cmake/windows/CMakeLists.txt:194 (SET_PROPERTY):
  SET_PROPERTY could not find TARGET PhysXVehicle.  Perhaps it has not yet
  been created.


CMake Error at submodules/PhysX/physx/source/compiler/cmake/windows/CMakeLists.txt:195 (SET_PROPERTY):
  SET_PROPERTY could not find TARGET PhysXVehicle2.  Perhaps it has not yet
  been created.


CMake Error at submodules/PhysX/physx/source/compiler/cmake/windows/CMakeLists.txt:196 (SET_PROPERTY):
  SET_PROPERTY could not find TARGET LowLevel.  Perhaps it has not yet been
  created.


CMake Error at submodules/PhysX/physx/source/compiler/cmake/windows/CMakeLists.txt:197 (SET_PROPERTY):
  SET_PROPERTY could not find TARGET LowLevelAABB.  Perhaps it has not yet
  been created.


CMake Error at submodules/PhysX/physx/source/compiler/cmake/windows/CMakeLists.txt:198 (SET_PROPERTY):
  SET_PROPERTY could not find TARGET LowLevelDynamics.  Perhaps it has not
  yet been created.


CMake Error at submodules/PhysX/physx/source/compiler/cmake/windows/CMakeLists.txt:199 (SET_PROPERTY):
  SET_PROPERTY could not find TARGET SceneQuery.  Perhaps it has not yet been
  created.


CMake Error at submodules/PhysX/physx/source/compiler/cmake/windows/CMakeLists.txt:200 (SET_PROPERTY):
  SET_PROPERTY could not find TARGET SimulationController.  Perhaps it has
  not yet been created.


CMake Error at submodules/PhysX/physx/source/compiler/cmake/windows/CMakeLists.txt:201 (SET_PROPERTY):
  SET_PROPERTY could not find TARGET FastXml.  Perhaps it has not yet been
  created.


CMake Error at submodules/PhysX/physx/source/compiler/cmake/windows/CMakeLists.txt:202 (SET_PROPERTY):
  SET_PROPERTY could not find TARGET PhysXPvdSDK.  Perhaps it has not yet
  been created.


CMake Error at submodules/PhysX/physx/source/compiler/cmake/windows/CMakeLists.txt:203 (SET_PROPERTY):
  SET_PROPERTY could not find TARGET PhysXTask.  Perhaps it has not yet been
  created.


CMake Error at submodules/PhysX/physx/source/compiler/cmake/windows/CMakeLists.txt:204 (SET_PROPERTY):
  SET_PROPERTY could not find TARGET PhysXFoundation.  Perhaps it has not yet
  been created.


CMake Error at submodules/PhysX/physx/source/compiler/cmake/windows/CMakeLists.txt:220 (INSTALL):
  INSTALL TARGETS given target "PhysXFoundation" which does not exist.


-- Configuring incomplete, errors occurred!
See also "G:/Development/Physx_cmake/cmake-build-debug/CMakeFiles/CMakeOutput.log".

[Failed to reload]


PxGjkQuery::proximityInfo not accurately computing the deepest points on shapes' surface

Library and Version

PhysX v5.1.0

Operating System

Linux

Code Snippet to Reproduce Behavior

SnippetArticulation.cpp

// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (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-2022 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.

// ****************************************************************************
// This snippet demonstrates the use of Reduced Coordinates articulations.
// ****************************************************************************

#include <ctype.h>
#include <vector>
#include <iostream>
#include "PxArticulationJointReducedCoordinate.h"
#include "PxPhysicsAPI.h"
#include "PxQueryReport.h"
#include "PxRigidActor.h"
#include "PxRigidStatic.h"
#include "PxVisualizationParameter.h"
#include "common/PxTolerancesScale.h"
#include "cooking/PxCooking.h"
#include "cooking/PxTriangleMeshDesc.h"
#include "extensions/PxExtensionsAPI.h"
#include "../snippetutils/SnippetUtils.h"
#include "../snippetcommon/SnippetPrint.h"
#include "../snippetcommon/SnippetPVD.h"

#include "../snippetrender/SnippetRender.h"
#include "../snippetrender/SnippetCamera.h"
#include "extensions/PxRigidBodyExt.h"
#include "extensions/PxSimpleFactory.h"
#include "foundation/Px.h"
#include "geometry/PxBoxGeometry.h"
#include "geometry/PxConvexMesh.h"
#include "geometry/PxConvexMeshGeometry.h"
#include "geometry/PxGeometry.h"
#include "geometry/PxGeometryHelpers.h"
#include "geometry/PxGeometryHit.h"
#include "geometry/PxGeometryQuery.h"

#include "geometry/PxGjkQuery.h"
#include "extensions/PxGjkQueryExt.h"
#include "geometry/PxSimpleTriangleMesh.h"
#include "geometry/PxTriangleMeshGeometry.h"
#include "pvd/PxPvd.h"
#include "../../include/omnipvd/PxOmniPvd.h"
#include "../../pvdruntime/include/OmniPvdFileWriteStream.h"
#include "../../pvdruntime/include/OmniPvdWriter.h"

#include "../snippetrender/SnippetRender.h"
#include "../snippetrender/SnippetCamera.h"

#include <memory>

using namespace physx;

static PxDefaultAllocator            gAllocator;
static PxDefaultErrorCallback          gErrorCallback;
static PxFoundation*              gFoundation    = NULL;
static PxPhysics*                gPhysics    = NULL;
static PxDefaultCpuDispatcher*          gDispatcher    = NULL;
static PxScene*                  gScene      = NULL;
static PxMaterial*                gMaterial    = NULL;
static PxOmniPvd* omniPvd = NULL;
static PxArticulationReducedCoordinate*      gArticulation  = NULL;

static Snippets::Camera* sCamera;

// TODO: Make these convex hulls (represented as meshes)
static PxRigidStatic *convexBody1;
static PxRigidStatic *convexBody2;

static PxConvexMeshGeometry* convexGeom1;
static PxConvexMeshGeometry* convexGeom2;

// Uses global vars...It's a test okay
void addConvexBodies() {
  // TODO: Create SSCH from 2 cuboids (extract vertices and stuff)
  PxVec3 convexVerts[] = {PxVec3(1.0, 1.0, 1.0),
                          PxVec3(-1.0, 1.0, 1.0),
                          PxVec3(1.0, -1.0, 1.0),
                          PxVec3(-1.0, -1.0, 1.0),
                          PxVec3(1.0, 1.0, -1.0),
                          PxVec3(-1.0, 1.0, -1.0),
                          PxVec3(1.0, -1.0, -1.0),
                          PxVec3(-1.0, -1.0, -1.0)};
  PxTolerancesScale tolerances;
  PxCookingParams params(tolerances); // TODO: Tolerances for what?
  PxConvexMeshDesc convexDesc;

  params.convexMeshCookingType = PxConvexMeshCookingType::eQUICKHULL;
  // disable mesh cleaning - perform mesh validation on development configurations
  params.meshPreprocessParams |= PxMeshPreprocessingFlag::eDISABLE_CLEAN_MESH;
  // disable edge precompute, edges are set for each triangle, slows contact generation
  params.meshPreprocessParams |= PxMeshPreprocessingFlag::eDISABLE_ACTIVE_EDGES_PRECOMPUTE;

  convexDesc.points.count = 8;
  convexDesc.points.stride = sizeof(PxVec3);
  convexDesc.points.data = convexVerts;
  // Needed when only providing vertices
  convexDesc.flags = PxConvexFlag::eCOMPUTE_CONVEX;
  convexDesc.flags |= PxConvexFlag::eDISABLE_MESH_VALIDATION;
  convexDesc.flags |= PxConvexFlag::eFAST_INERTIA_COMPUTATION;

  PxConvexMesh* aConvexMesh = PxCreateConvexMesh(params, convexDesc,
                                                 gPhysics->getPhysicsInsertionCallback());

  convexGeom1 = new PxConvexMeshGeometry(aConvexMesh);
  PxTransform convexPose1 = PxTransform(PxIdentity);
  convexBody1 = gPhysics->createRigidStatic(convexPose1);
  PxRigidActorExt::createExclusiveShape(*convexBody1, *convexGeom1, *gMaterial);
  gScene->addActor(*convexBody1);

  convexGeom2 = new PxConvexMeshGeometry(aConvexMesh);
  PxTransform convexPose2 = PxTransform(PxIdentity);
  convexPose2.p = PxVec3(1,1,1);
  convexBody2 = gPhysics->createRigidStatic(convexPose2);
  PxRigidActorExt::createExclusiveShape(*convexBody2, *convexGeom2, *gMaterial);
  gScene->addActor(*convexBody2);
}

void initPhysics(bool /*interactive*/)
{

  gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
  omniPvd = PxCreateOmniPvd(*gFoundation);
  OmniPvdWriter* omniWriter = omniPvd->getWriter();
  // omniWriter->setLogFunction([](char *logMsg) {std::cout << logMsg << std::endl;});

  OmniPvdFileWriteStream* omniFileWriteStream = omniPvd->getFileWriteStream();
  omniWriter->setWriteStream(omniFileWriteStream);

  gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(), true, nullptr, omniPvd);

  omniFileWriteStream->setFileName("/tmp/myoutpufile.ovd");
  omniPvd->startSampling();

  PxInitExtensions(*gPhysics, nullptr);

  PxSceneDesc sceneDesc(gPhysics->getTolerancesScale());
  sceneDesc.gravity = PxVec3(0.0f, -9.81f, 0.0f);

  PxU32 numCores = SnippetUtils::getNbPhysicalCores();
  gDispatcher = PxDefaultCpuDispatcherCreate(numCores == 0 ? 0 : numCores - 1);
  sceneDesc.cpuDispatcher  = gDispatcher;
  sceneDesc.filterShader  = PxDefaultSimulationFilterShader;

  sceneDesc.solverType = PxSolverType::eTGS;

  gScene = gPhysics->createScene(sceneDesc);
  gScene->setVisualizationParameter(PxVisualizationParameter::eSCALE, 1.0f); // TODO: Needed?

  gMaterial = gPhysics->createMaterial(0.5f, 0.8f, 0.3f);

  PxRigidStatic* groundPlane = PxCreatePlane(*gPhysics, PxPlane(0,1,0,0), *gMaterial);

  // Add actors
  gScene->addActor(*groundPlane);
  // Add collision body actors
  addConvexBodies();

  gScene->setGravity(PxVec3(0,0,0));
  gScene->setVisualizationParameter(PxVisualizationParameter::eCOLLISION_SHAPES, 1);
  gScene->setVisualizationParameter(PxVisualizationParameter::eACTOR_AXES, 1);
}

// static bool gClosing = true;
static int tick = 0;
void stepPhysics(bool /*interactive*/)
{
  int tick_every = 500;
  tick++;
  if(tick > tick_every)
  {
    tick= 0;
    const PxReal dt = 1.0f / 60.f;

    gScene->simulate(dt);
    gScene->fetchResults(true);

  }

}

void cleanupPhysics(bool /*interactive*/)
{
  gArticulation->release();
  PX_RELEASE(gScene);
  PX_RELEASE(gDispatcher);
  PX_RELEASE(gPhysics);
  PX_RELEASE(omniPvd);
  PxCloseExtensions();
  PX_RELEASE(gFoundation);

  printf("SnippetArticulation done.\n");
}


void renderCallback()
{
  stepPhysics(true);

  Snippets::startRender(sCamera);

  const PxVec3 dynColor(1.0f, 0.5f, 0.25f);
  const PxVec3 rcaColor(0.6f*0.75f, 0.8f*0.75f, 1.0f*0.75f);

  PxScene* scene;
  PxGetPhysics().getScenes(&scene,1);
  PxU32 nbActors = scene->getNbActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC);
  if(nbActors)
  {
    std::vector<PxRigidActor*> actors(nbActors);
    scene->getActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC, reinterpret_cast<PxActor**>(&actors[0]), nbActors);
    Snippets::renderActors(&actors[0], static_cast<PxU32>(actors.size()), true, dynColor);
  }

  // Render witness points using simple OpenGL line
  auto convexSupport1 = PxGjkQueryExt::ConvexMeshSupport(*convexGeom1);
  auto convexSupport2 = PxGjkQueryExt::ConvexMeshSupport(*convexGeom2);

  PxVec3 pointA;
  PxVec3 pointB;
  PxVec3 separatingAxis;
  PxReal separation;

  PxGjkQuery::proximityInfo(convexSupport1, convexSupport2, convexBody1->getGlobalPose(), convexBody2->getGlobalPose(), 0, 0, pointA, pointB, separatingAxis, separation);
  std::cout << "Point A: " << pointA.x << " " << pointA.y << " " << pointA.z << std::endl;
  std::cout << "Point B: " << pointB.x << " " << pointB.y << " " << pointB.z << std::endl;
  std::cout << "Separation Axis: " << separatingAxis.x << " " << separatingAxis.y << " " << separatingAxis.z << std::endl;
  std::cout << "Separation Distance: " << separation << std::endl;

  // Draw line between witness points (only visible after pressing
  // 'n' in the snippet OpenGL visualizer)
  // Actual result
  glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
  glBegin(GL_LINES);
  glVertex3f(pointA.x, pointA.y, pointA.z);
  glVertex3f(pointB.x, pointB.y, pointB.z);
  glEnd();

  // Expected result
  glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
  glBegin(GL_LINES);
  glVertex3f(1.0f, 1.0f, 1.0f);
  glVertex3f(0.0f, 0.0f, 0.0f);
  glEnd();

  Snippets::finishRender();
}

void exitCallback(void)
{
  cleanupPhysics(true);
}

const PxVec3 gCamEyeLift(-5.858525f, 1.0f, 1.546743f); // y=6.079476f
const PxVec3 gCamDirLift(0.927923f, -0.356565f, -0.108720f);

void newRenderLoop()
{
  sCamera = new Snippets::Camera(gCamEyeLift, gCamDirLift);

  Snippets::setupDefault("PhysX Snippet RC Articulation", sCamera, NULL, renderCallback, exitCallback);

  initPhysics(true);
  glutMainLoop();
}

int snippetMain(int, const char*const*)
{
  newRenderLoop();
  return 0;
}

Screenshot from 2023-03-01 12-31-22

Expected Behavior

Expected PxGjkQuery::proximityInfo to output the deepest points on the shapes' surface, with the line between shown above in blue.

Expected deepest points:

Point A: 1.0 1.0 1.0
Point B: 0.0 0.0 0.0

Actual Behavior

PxGjkQuery::proximityInfo returns a point on the shapes' surface, with the line between shown above in red.

The program outputs:

Point A: 1.0 0.5 0.5
Point B: 0.0 0.5 0.5

include errors when compiling header files

PhysX v5.1.0

Operating System

Manjaro Linux

Steps to Trigger Behavior

  1. Make your custom code
  2. when compiling your code, reference the include folder: PhysX/physx/include
  3. this error or similar should appear
/run/media/nonunknown/3a1f3657-ce4a-4ffa-8f65-f41e1dfcaf68/PhysX/physx/include/foundation/Px.h:36:10: fatal error: foundation/PxSimpleTypes.h: No such file or directory
   36 | #include "foundation/PxSimpleTypes.h"
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
scons: *** [src/example.os] Error 1
In file included from /run/media/nonunknown/3a1f3657-ce4a-4ffa-8f65-f41e1dfcaf68/PhysX/physx/include/PxPhysicsAPI.h:43,
                 from src/example.h:25,
                 from src/register_types.cpp:14:
/run/media/nonunknown/3a1f3657-ce4a-4ffa-8f65-f41e1dfcaf68/PhysX/physx/include/foundation/Px.h:36:10: fatal error: foundation/PxSimpleTypes.h: No such file or directory
   36 | #include "foundation/PxSimpleTypes.h"
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
scons: *** [src/register_types.os] Error 1

Expected Behavior

Fine Compilation

Actual Behavior

Error message

Modify CMakeModules package Packman downloads to include Android, iOS and Mac platforms

The name of the bin folders will be incorrect when building for Android, iOS and Mac-arm64.

To fix this nVidia has to modify the CMakeModules package it's downloaded from packman when building PhysX, since it's not part of the Github repo.

The file that needs to be modified is GetCompilerAndPlatform.cmake, changing the if condition inside GetPlatformBinName function to this:

	ELSEIF(TARGET_BUILD_PLATFORM STREQUAL "mac")
		IF(${PX_OUTPUT_ARCH} STREQUAL "x86")
			SET(RETVAL "mac.x86_${LIBPATH_SUFFIX}")
		ELSEIF(${PX_OUTPUT_ARCH} STREQUAL "arm")
			SET(RETVAL "mac.arm64")
		ENDIF()
	ELSEIF(TARGET_BUILD_PLATFORM STREQUAL "ios")
		SET(RETVAL "ios.arm_${LIBPATH_SUFFIX}")
	ELSEIF(TARGET_BUILD_PLATFORM STREQUAL "android")
		SET(RETVAL "android.${ANDROID_ABI}")

This code modification was tested locally on these PRs: #40 #49 #51

Possible thread safety issue with interaction handling

Hi

We are having an issue with corrupted mActiveInteractionCount in Sc::Scene ( values < 0 or incoherent with Interaction's id ) , after inquiring the issue we think we found two similar thread safety issues with Interaction handling.

Library and Version

PhysX v5.1.0

Operating System

Windows 10 / Windows 11

Code to Reproduce Behavior

Thread safety issue 1

In Sc::Scene::postIslandGen, mSetEdgesConnectedTask and mNPhaseCore->processTriggerInteractions can be called in concurrent tasks,

void Sc::Scene::postIslandGen(PxBaseTask* continuationTask)
{
PX_PROFILE_ZONE("Sim.postIslandGen", getContextId());
mSetEdgesConnectedTask.setContinuation(continuationTask);
mSetEdgesConnectedTask.removeReference();
// - Performs collision detection for trigger interactions
mNPhaseCore->processTriggerInteractions(continuationTask);
}

Task 1

mSetEdgesConnectedTask will call Sc::Scene::setEdgesConnected wich in turn call wakeObjectsUp

void Sc::Scene::setEdgesConnected(PxBaseTask*)
{
PX_PROFILE_ZONE("Sim.preIslandGen.islandTouches", getContextId());
{
PX_PROFILE_ZONE("Sim.preIslandGen.setEdgesConnected", getContextId());
const PxU32 newTouchCount = mTouchFoundEvents.size();
for(PxU32 i = 0; i < newTouchCount; ++i)
{
ShapeInteraction* si = getSI(mTouchFoundEvents[i]);
if(!si->readFlag(ShapeInteraction::CONTACTS_RESPONSE_DISABLED))
mSimpleIslandManager->setEdgeConnected(si->getEdgeIndex(), IG::Edge::eCONTACT_MANAGER);
}
}
mSimpleIslandManager->secondPassIslandGen();
wakeObjectsUp(ActorSim::AS_PART_OF_ISLAND_GEN);
}

wakeObjectsUp may activate actors and their Interactions, wich will end up calling Sc::Scene::notifyInteractionActivated
Heres is a possible callstack :

 physx::Sc::Scene::setEdgesConnected(physx::PxBaseTask * __formal)
	physx::Sc::Scene::wakeObjectsUp(unsigned int infoFlag)
		physx::Sc::ActorSim::setActive(bool active, unsigned int infoFlag)
			physx::Sc::BodySim::activate()
				physx::Sc::activateInteractions(physx::Sc::ActorSim & actorSim)
					physx::Sc::Scene::notifyInteractionActivated(physx::Sc::Interaction * interaction)

Task 2

mNPhaseCore->processTriggerInteractions calls NPhaseCore::mergeProcessedTriggerInteractions wich will call Sc::Scene::notifyInteractionDeactivated

void NPhaseCore::mergeProcessedTriggerInteractions(PxBaseTask*)
{
if(mTmpTriggerProcessingBlock)
{
// deactivate pairs that do not need trigger checks any longer (until woken up again)
TriggerInteraction** triggerPairsToDeactivate = reinterpret_cast<TriggerInteraction**>(mTmpTriggerProcessingBlock);
for(PxI32 i=0; i < mTriggerPairsToDeactivateCount; i++)
{
mOwnerScene.notifyInteractionDeactivated(triggerPairsToDeactivate[i]);
}
mTriggerPairsToDeactivateCount = 0;
mOwnerScene.getLowLevelContext()->getScratchAllocator().free(mTmpTriggerProcessingBlock);
mTmpTriggerProcessingBlock = NULL;
}
}

Result

Unfortunately it does not seem to be valid to call Sc::Scene::notifyInteractionActivated and Sc::Scene::notifyInteractionDeactivated concurrently causing corrupted interactions count and indices.

A possible fix would be to modify Sc::Scene::postIslandGen to add a dependency between mSetEdgesConnectedTask and mNPhaseCore->processTriggerInteractions

void Sc::Scene::postIslandGen(PxBaseTask* continuationTask)
{
	PX_PROFILE_ZONE("Sim.postIslandGen", getContextId());

	mSetEdgesConnectedTask.setContinuation(continuationTask);

	// - Performs collision detection for trigger interactions
	mNPhaseCore->processTriggerInteractions( &mSetEdgesConnectedTask );
	mSetEdgesConnectedTask.removeReference();
}

Thread safety issue 2

A similar issue is located in Sc::Scene::processLostContacts2, Sc::Scene::lostTouchReports and Sc::Scene::unregisterInteractions will be called concurrently,

void Sc::Scene::processLostContacts2(PxBaseTask* continuation)
{
mDestroyManagersTask.setContinuation(continuation);
mLostTouchReportsTask.setContinuation(&mDestroyManagersTask);
mLostTouchReportsTask.removeReference();
mUnregisterInteractionsTask.setContinuation(continuation);
mUnregisterInteractionsTask.removeReference();

Task 1

Sc::Scene::lostTouchReports will wake actors on lost touch, wich will end up calling Sc::Scene::notifyInteractionActivated

void Sc::Scene::lostTouchReports(PxBaseTask*)
{
PX_PROFILE_ZONE("Sim.lostTouchReports", getContextId());
PxsContactManagerOutputIterator outputs = mLLContext->getNphaseImplementationContext()->getContactManagerOutputs();
Bp::AABBManagerBase* aabbMgr = mAABBManager;
PxU32 destroyedOverlapCount;
mNPhaseCore->lockReports();
{
const Bp::AABBOverlap* PX_RESTRICT p = aabbMgr->getDestroyedOverlaps(Bp::ElementType::eSHAPE, destroyedOverlapCount);
while(destroyedOverlapCount--)
{
if(p->mPairUserData)
{
Sc::ElementSimInteraction* elemInteraction = reinterpret_cast<Sc::ElementSimInteraction*>(p->mPairUserData);
if(elemInteraction->getType() == Sc::InteractionType::eOVERLAP)
mNPhaseCore->lostTouchReports(static_cast<Sc::ShapeInteraction*>(elemInteraction), PxU32(PairReleaseFlag::eWAKE_ON_LOST_TOUCH), NULL, 0, outputs);
}
p++;
}
}
mNPhaseCore->unlockReports();
}

Here is a possible callstack :

physx::Sc::Scene::lostTouchReports(physx::PxBaseTask * __formal)
	physx::Sc::NPhaseCore::lostTouchReports(physx::Sc::ShapeInteraction * si, unsigned int flags, physx::Sc::ElementSim * removedElement, const unsigned int ccdPass, physx::PxsContactManagerOutputIterator & outputs)
		physx::Sc::BodySim::internalWakeUp(float wakeCounterValue)
			physx::Sc::BodySim::internalWakeUpBase(float)
				physx::Sc::ActorSim::setActive(bool active, unsigned int infoFlag)
					physx::Sc::BodySim::activate()
						physx::Sc::activateInteractions(physx::Sc::ActorSim & actorSim)
							physx::Sc::Scene::notifyInteractionActivated(physx::Sc::Interaction * interaction)

Task 2

Sc::Scene::unregisterInteractions will call Sc::Scene::unregisterInteraction .

void Sc::Scene::unregisterInteractions(PxBaseTask*)
{
PX_PROFILE_ZONE("Sim.unregisterInteractions", getContextId());
Bp::AABBManagerBase* aabbMgr = mAABBManager;
PxU32 destroyedOverlapCount;
{
const Bp::AABBOverlap* PX_RESTRICT p = aabbMgr->getDestroyedOverlaps(Bp::ElementType::eSHAPE, destroyedOverlapCount);
while(destroyedOverlapCount--)
{
if(p->mPairUserData)
{
Sc::ElementSimInteraction* elemInteraction = reinterpret_cast<Sc::ElementSimInteraction*>(p->mPairUserData);
if(elemInteraction->getType() == Sc::InteractionType::eOVERLAP || elemInteraction->getType() == Sc::InteractionType::eMARKER)
{
unregisterInteraction(elemInteraction);
mNPhaseCore->unregisterInteraction(elemInteraction);
}
}
p++;
}
}
}

Result

Similarly to the first issue Sc::Scene::notifyInteractionActivated and Sc::Scene::unregisterInteraction are not safe to be called concurrently.

The possible fix in Sc::Scene::processLostContacts2 is to add a dependency between Sc::Scene::lostTouchReports and Sc::Scene::unregisterInteractions tasks :
Before :

void Sc::Scene::processLostContacts2(PxBaseTask* continuation)
{
mDestroyManagersTask.setContinuation(continuation);
mLostTouchReportsTask.setContinuation(&mDestroyManagersTask);
mLostTouchReportsTask.removeReference();
mUnregisterInteractionsTask.setContinuation(continuation);
mUnregisterInteractionsTask.removeReference();

After :

void Sc::Scene::processLostContacts2(PxBaseTask* continuation)
{
	mDestroyManagersTask.setContinuation(continuation);
	mLostTouchReportsTask.setContinuation( &mDestroyManagersTask );

	mUnregisterInteractionsTask.setContinuation( &mLostTouchReportsTask );
	mUnregisterInteractionsTask.removeReference();
	mLostTouchReportsTask.removeReference();

Doesn't compile when targeting `aarch64-apple-darwin`

Library and Version

5.1.3

Operating System

aarch64-apple-darwin

Steps to Trigger Behavior

  1. Try to compile for aarch64-apple-darwin
  2. Failure

Code Snippet to Reproduce Behavior

Irrelevant

Expected Behavior

PhysX compiles

Actual Behavior

PhysX fails to compile for several reasons:

  1. FdUnixFPU.cpp includes <xmmintrin.h> if PX_OSX is 1, which fails since that is an x86 only header. See EmbarkStudios@1e04de1 for a commit to fix this
  2. SIMD is not properly enabled in PxVecMath.h, causing failures in other code that doesn't have the same guard. See EmbarkStudios@33e5eb7 for a commit to fix this.
  3. SnSerialUtils.cpp fails to compile due to no case matching aarch64 and OSX, resulting in Unknown binary platform. See EmbarkStudios@720c8a5 for a patch to fix this.

FYI, the only reason that PhysX 4.1 compiled for aarch64-apple-darwin was because it misidentified the target to PX_IOS

https://github.com/NVIDIAGameWorks/PhysX/blob/a2c0428acab643e60618c681b501e86f7fd558cc/pxshared/include/foundation/PxPreprocessor.h#L103-L106

But it appears like iOS support has been completely dropped in PhysX 5 (with no CHANGELOG entry) resulting in these errors.

CUDA Rigidbodies extremely unstable when initializing with setGlobalPose instead of setLocalPose

If you initialize CUDA rigidbodies in certain configurations with setGlobalPose instead of setLocalPose, they will behave erratically. The erratic behavior does not happen in CPU mode.

This bug report is an extension of a discussion I started last week (#99). I am logging it as a bug because I have created a fully reproducible snippet showcasing the erratic behavior.

In my snippet I create a scene, simulate for a couple of time steps, then cleanup the scene and repeat that process many times - only displaying the final result after all timesteps are simulated each iteration.

When I initialize the rigidbodies by establishing their global pose at the scene origin, and moving their shape local pose into the desired place in the world, the simulation is fully deterministic.

When I do the opposite - establish their shape local pose at the rigidbody origin and move their rigidbody global pose into the desired place in the world, the simulation behaves erratically and is no longer deterministic. Often, angular/linear velocities returned are NaNs.

The video below demonstrates the result:

badcuda2.mp4

And here is the snippet. Replace the existing files in the PhysX "SnippetHelloGRB" project with these two, and uncomment lines 248/249 to see the erratic behavior.

unstableCUDA.zip

badcuda

Note: The rigidbodies in this snippet are initialized in a manner that causes them all to slightly overlap on their start frame. This is by design, as the erratic behavior occurs most often when starting penetrations exist, in my tests.

Ubuntu - undefined reference to PxSetPhysXGpuProfilerCallback

I seem to have the libraries(.lib files) successfully linked on Linux via Cmake, but I am getting the following error:
PxPvdImpl.cpp:108: undefined reference to 'PxSetPhysXGpuProfilerCallback'

It appears it is trying to include code that is for the PhysXGpu library, which to my knowledge is supposed to optional? It it is not, how would I link it to my project? I tried linking the dll, but that caused other undefined references, so I'm assuming PhysXGpu has some dependencies of it's own.

I found a preprocessor directive "DISABLE_CUDA_PHYSX" that looks like it'd avoid the calls to PhysXGpu, but defining it didn't seem to make a difference.

Error while generating projects

After downloading and running the generatre_projects.bat I get this error

Creating directory C:\packman-repo
Fetching [email protected]_64.cab ...
Downloading from bootstrap.packman.nvidia.com ...
Unpacking Python interpreter ...
Fetching [email protected] ...
Downloading from bootstrap.packman.nvidia.com ...
Unpacking ...
Processing project file 'C:\packman-repo\packman-common\6.33.2\deps.packman.xml'
Package '7za' at version '16.02.4' is missing from local storage.
Downloading from http://bootstrap.packman.nvidia.com/7za%4016.02.4.zip (4.33 MiB)
100.00% (speed 4.32 MiB/s)
Total of 1.00 seconds
Unzipping: [email protected] (9.87 MiB)
100.00% (speed 90.1 MiB/s)
Total of 0.11 seconds
Package successfully installed to C:\packman-repo\chk\7za\16.02.4
File "C:/Users/Vincenzo", line 1
[1E40:0114][2023-05-24T17:01:31]i001: Burn v3.10.4.4718, Windows v10.0 (Build 19045: Service Pack 0), path: C:\WINDOWS\Temp{6B707990-D955-4EF1-BCBC-78CDEDDE1213}.cr\VC_redist.x64.exe
^
SyntaxError: invalid syntax
Hit ENTER to continue...

Library and Version

Operating System

Steps to Trigger Behavior

Code Snippet to Reproduce Behavior

<your-snippet>

Expected Behavior

Actual Behavior

Possible Improvment: $(SolutionDir)

I wish I knew CMake better, it does look like a cool tool. As you may know Visual Studio does have a few macros that may be helpful and accessible to CMake. The first image shows the PhysX project configuration properties for a debug build. The second image shows all the projects selected and for all configurations. The end goal is to be able to move projects to different drives or rename top level directories without having dependencies. Please let me know if you have any interest in discussing this or me submitting changes (but would need some help with CMake changes).

PhysXDebugProps

PhysXAll

Getting NaN link velocities with a simple PxArticulationReducedCoordinate

Library and Version

PhysX 5.1.0

Operating System

Linux

Code Snippet to Reproduce Behavior

physx::PxArticulationReducedCoordinate* create_single_joint_articulation(physx::PxPhysics& physics)
{
    physx::PxArticulationReducedCoordinate* articulation = physics.createArticulationReducedCoordinate();
    articulation->setArticulationFlags(physx::PxArticulationFlag::eFIX_BASE);
    material = physics.createMaterial(0.5f, 0.8f, 0.3f);

    // essentially a big rotating cube (1m)
    const physx::PxBoxGeometry link_geometry = physx::PxBoxGeometry(1.0);
    // add a second link still at identity
    auto root_link = articulation->createLink(nullptr, physx::PxTransform());
    physx::PxRigidActorExt::createExclusiveShape(*root_link, link_geometry, *material);

    // add a second link still at identity
    auto link = articulation->createLink(root_link, physx::PxTransform(1,0,0));
    physx::PxRigidActorExt::createExclusiveShape(*link, link_geometry, *material);
    physx::PxTransform on_x(1,0,0);
    // No need to fiddle with the joint as we're not setting limits
    auto joint = static_cast<physx::PxArticulationJointReducedCoordinate*>(link->getInboundJoint());
    joint->setParentPose(on_x);
    joint->setJointType(physx::PxArticulationJointType::eREVOLUTE);
    joint->setMotion(physx::PxArticulationAxis::eTWIST, physx::PxArticulationMotion::eFREE);
    return articulation;
}

void printVel(const physx::PxSpatialVelocity& t)
{
  std::cout << "v: [" << t.linear.x << "," << t.linear.y << "," << t.linear.z << "]";
  std::cout << "w: [" << t.angular.x << "," << t.angular.y << "," << t.angular.z << "]" << std::endl;
}

int main()
{
    physx::PxDefaultAllocator allocator;
    physx::PxDefaultErrorCallback error_callback;
    physx::PxFoundation* foundation = PxCreateFoundation(PX_PHYSICS_VERSION, allocator, error_callback);
    physx::PxPhysics* physics = PxCreatePhysics(PX_PHYSICS_VERSION, *foundation, physx::PxTolerancesScale(), true, nullptr);
    physx::PxSceneDesc scene_desc(physics->getTolerancesScale());
    physx::PxScene* scene = physics->createScene(scene_desc);

    auto art = create_single_joint_articulation(*physics);

    scene->addArticulation(*robot);
    art ->zeroCache(*cache);
    cache->jointVelocity[0] = 1;
    art ->applyCache(*cache, physx::PxArticulationCacheFlag::eALL);
    art ->copyInternalStateToCache(*cache, physx::PxArticulationCacheFlag::eALL);
    printVel(cache->linkVelocity[1]);
}

Expected Behavior

I would expect the velocity of the second link to be some non-zero value if the first joint is moving at 1m/s

Actual Behavior

The output of the above program is

v: [nan,-nan,-nan]w: [-nan,-nan,-nan]

I don't understand why the link velocities in this case will ever be NaN

generate_projects downloads bootstrap packages without TLS

Library and Version

Release 104.0.

Operating System

Any.

Steps to Trigger Behavior

  1. Run build script.
  2. Observe that TLS is not used to connect to bootstrap.packman.nvidia.com.

Code Snippet to Reproduce Behavior

$ bash generate_projects.sh linux

Expected Behavior

Build script connects to bootstrap.packman.nvidia.com over TLS.

Actual Behavior

Build script connects to bootstrap.packman.nvidia.com without TLS, allowing an attacker to replace python and packman-common with malicious versions. Ideally, the build script would also verify checksums after downloading files.

Vehicle slides down slope when stationary

Hi there,

I'm using the SnippetVehicleDirectDrive, and when I change the infinite ground plane to have even a small angle of 5 degrees in the longitudinal direction of the vehicle. The vehicle is unable to stay stationary even when the brakes are applied. It slides (not roll, the wheels are not spinning) down the slope. What do I need to change to make sure that this doesn't happen?

Additionally if I set the ground plane to have a small slope in the lateral direction the vehicle slides down laterally but not continuously, it just slides for a bit then stops and slides again.

Thanks

Assert in suspension on flipped vehicle.

It seems like suspDirVelWheel should be used in line 373.

if (jounceSpeed < (-suspDirVelWheel))
{
// The suspension can not expand fast enough to place the wheel on the ground. As a result,
// the scenario is interpreted as if there was no hit and the wheels end up in air. The
// jounce is adjusted based on the clamped velocity to not have it snap to 0 immediately.
// note: could consider applying the suspension force to the sprung mass too but the complexity
// seems high enough already.
const PxReal expansionDelta = suspDirVel * dt;
const PxReal clampedJounce = previousJounce - expansionDelta;
PX_ASSERT(clampedJounce >= 0.0f);

Otherwise, the assert in line 376 is not guaranteed for cases where -gravitySuspDir * dt * dt > previousJounce + jounceSpeed * dt. It is possible case when vehicle is flipped.

Library and Version

PhysX v5.1.2

Operating System

Window 10

Missing SDF collisions in CPU mode

If I setup a dynamic rigidbody with an SDF collider (using settings similar to those in the SDF snippet), I get expected results when simulating on the GPU (collisions between dynamic SDF and static ground collider, collisions between multiple dynamic SDF meshes).

However, if I simulate on the CPU, the SDF colliders will collide with kinematic rigidbodies and rigidbodies with box/sphere/convex hulls, but won't collide other rigidbodies with SDF hulls and won't collide with static colliders.

generate_projects.sh script behaves differently on different devices

Hi, I'm trying to automate a pipeline with docker and build PhysX within it and I noticed when running ./generate_projects.sh that to build for aarch64 or clang (the two options it presents) are in different order on different devices. For example (0) is clang on the pipeline that I'm trying to automate but (0) is aarch64 on my laptop. This makes it difficult to automate the pipeline by simply being able to pass in a (0) or (1) into the script based on your hardware because (0) and (1) are different in different environments.

image

vs

image

Add to packman the arm-based version of python for Mac

Python package used by packman on Mac is always the x86_64 architecture one and when trying to build with an arm-based Mac it generates the error dyld[number]: missing symbol called.

To fix this nVidia has to add an ARM python package for mac into the packman scripts here https://github.com/NVIDIA-Omniverse/PhysX/blob/release/104.1/physx/buildtools/packman/packman#L81-#L82 to something like this:

	if [ $PLATFORM == 'Darwin' ] && [ $PROCESSOR == 'x86_64' ]; then
		PYTHON_PACKAGE=$PYTHON_VERSION-macos-x86_64
	elif [ $PLATFORM == 'Darwin' ] && [ $PROCESSOR == 'arm64' ]; then
		PYTHON_PACKAGE=$PYTHON_VERSION-macos-arm64  # This package doesn't exist at the moment, NVIDIA has create it and make it available to fetch from S3.

Temporary Workaround
As a temporary solution, you can use your system's python by adding the environment variable PM_PYTHON_EXT before building, for example by adding export PM_PYTHON_EXT="python3" into your .bash_profile file.

Related PR: #51

macOS build of blast checks for wrong uname output

% cd blast
% ./build.sh
[ERROR][omni.repo.man.guidelines] Unsupported host platform: darwin-x86_64, only ['windows-x86_64', 'linux-x86_64', 'linux-aarch64', 'macos-x86_64', 'macos-aarch64'] are supported.

% uname -a
Darwin jordanh-mlt 22.1.0 Darwin Kernel Version 22.1.0: Sun Oct 9 20:15:09 PDT 2022; root:xnu-8792.41.9~2/RELEASE_ARM64_T6000 arm64

This is an Apple Silicon Mac so both the output (claiming a darwin-x86_64 host platform) and the uname check is erroneous. macos has always identified itself as "Darwin" due to its roots, never "macos".

Stage Properties crashes Flow exampple

For PhysX Flow 5.1.0 on my Windows 10, when I click the Stage Properties in the Flow example, the thing thing crashes. Error, if I have no break points points the the problem being line 4781 in imgui.cpp.

Solution Generation and Building doesn't work in folders which contain spaces

Library and Version

PhysX v5.1.3

Operating System

Windows 11

Steps to Trigger Behavior

  1. Extract a release into a folder in windows constaining a space, like "C:/Test Folder"
  2. Try to follow normal build/generate/compile instructions
  3. Everything fails due to (I assume CMake or python scripts) not handling a space in a folder

Code Snippet to Reproduce Behavior

No code required.

Expected Behavior

To be able to put this on a users machine, inside a folder which contains a space, and that it works.

Actual Behavior

It won't build solutions, and it isn't possible to generate solutions in another folder and then copy them over due to how everything is hardlinking everything else instead of using $(SolutionDir) and relative paths.

Negative TOI calculation problem for Convex- TriangleMesh CCD

ไผไธšๅพฎไฟกๆˆชๅ›พ_16759133925174

https://github.com/NVIDIA-Omniverse/PhysX/blob/release/104.1/physx/source/geomutils/src/ccd/GuCCDSweepConvexMesh.cpp

In GuCCDSweepConvexMesh.cpp, Line 555 to Line 584, it is calculating the penetration if TOI < 0 after SweepShapeTriangle. However, the distanceSq makes me confused. Since sphereCenterInTransform1 is always identity ๏ผˆtrimesh must be static). So the distance is from triangle mesh vertex space origin to the hit triangle, but it is arbitrary๏ผŒsince triangle mesh vertex space origin can be anywhere. So the TOI (negative means penetration) might be wrong in this case.

There are still other problems:

  1. SweepAnyShapeHeightfield seems to be more reasonable but sphereCenterInTr1 and sphereCenterInTr1T0 is the same.
  2. Line 310 & 576 is opposite (dd > d or dd < d ?).
  3. The "res = -(2.f * inSphereRadius - distance)" looks strange too, I cannot find its geometrical interpretation.

triangle mesh collision with particles-cloth on GPU

Hi, thanks for your great work, I'm trying to combine "snippethelloworld" , "snippetimmediatemode" and "snippetpbdcloth" into a new demo, but "Cloth" seems doesn't has the collision with the triangles mesh, does PhysX support collision between these objetcs or how can I set flags for coolision.
and the output of physx is
[100%] Built target SnippetSimpleDemo /buildAgent/work/2a49d215dfbd0a40/source/gpunarrowphase/src/PxgNphaseImplementationContext.cpp (1671) : internal error : Non GPU compatible triangle mesh isn't allowed to collied with particle system fail!!

and images are list here
Screenshot from 2022-11-17 21-46-35
Screenshot from 2022-11-17 21-46-54
Screenshot from 2022-11-17 21-47-05
Screenshot from 2022-11-17 21-47-16

and the code are list here:

#include "../snippetrender/SnippetCamera.h"
#include "../snippetrender/SnippetRender.h"
#include "../snippetutils/SnippetUtils.h"
#include "PxPhysicsAPI.h"
#include "cudamanager/PxCudaContext.h"
#include "cudamanager/PxCudaContextManager.h"
#include "extensions/PxParticleExt.h"

#include <iostream>
#include <vector>

using namespace physx;
using namespace ExtGpu;

static PxDefaultAllocator      gAllocator;
static PxDefaultErrorCallback  gErrorCallback;
static PxFoundation*           gFoundation     = nullptr;
static PxPhysics*              gPhysics        = nullptr;
static PxDefaultCpuDispatcher* gDispatcher     = nullptr;
static PxScene*                gScene          = nullptr;
static PxMaterial*             gMaterial       = nullptr;
static PxPBDParticleSystem*    gParticleSystem = nullptr;
static PxParticleClothBuffer*  gClothBuffer    = nullptr;
static bool                    gIsRunning      = false;

Snippets::Camera*        sCamera = nullptr;
PxReal                   simTime = 0;
Snippets::SharedGLBuffer sPosBuffer;

void keyCallback(unsigned char key, const PxTransform&) {
    switch (toupper(key)) {
    case ' ':
        gIsRunning = !gIsRunning;
        break;

    default:
        break;
    }
}

void stepPhysics(bool) {
    if (gIsRunning) {
        const PxReal dt = 1.0f / 60.0f;

        gScene->simulate(dt);
        gScene->fetchResults(true);
        gScene->fetchResultsParticleSystem();
        simTime = simTime + dt;
    }
}

void onBeforeRenderParticles() {
    if (gParticleSystem) {
        PxVec4*     positions    = gClothBuffer->getPositionInvMasses();
        const PxU32 numParticles = gClothBuffer->getNbActiveParticles();

        PxCudaContextManager* cudaContextManager = gScene->getCudaContextManager();
        cudaContextManager->acquireContext();

        PxCudaContext* cudaContext = cudaContextManager->getCudaContext();
        cudaContext->memcpyDtoH(sPosBuffer.map(), CUdeviceptr(positions), sizeof(PxVec4) * numParticles);

        cudaContextManager->releaseContext();
        // #if SHOW_SOLID_SDF_SLICE
        //         particleSystem->copySparseGridData(sSparseGridSolidSDFBufferD, PxSparseGridDataFlag::eGRIDCELL_SOLID_GRADIENT_AND_SDF);
        // #endif
    }
}

void renderParticles() {
    sPosBuffer.unmap();

    PxVec3 color(1.0f, 0.3f, 0.5);
    Snippets::DrawPoints(sPosBuffer.vbo, sPosBuffer.size / sizeof(PxVec4), color, 2.0f);
    Snippets::DrawFrame(PxVec3(0, 0, 0));
}

void renderCallback() {
    onBeforeRenderParticles();

    stepPhysics(true); // all render/ simulate in this function.

    Snippets::startRender(sCamera);

    PxU32 nbActors = gScene->getNbActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC);
    if (nbActors) {
        std::vector<PxRigidActor*> actors(nbActors);
        gScene->getActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC, reinterpret_cast<PxActor**>(&actors[0]), nbActors);
        Snippets::renderActors(&actors[0], static_cast<PxU32>(actors.size()), false);
    }

    renderParticles();

    Snippets::finishRender();
}

void cleanupPhysics() {
    PX_RELEASE(gScene);
    PX_RELEASE(gDispatcher);
    PX_RELEASE(gFoundation);
}

void exitCallback() {
    delete sCamera;
}

static PX_FORCE_INLINE PxU32 id(PxU32 x, PxU32 y, PxU32 numY) {
    return x * numY + y;
}

void initCloth(const PxU32 numX, const PxU32 numZ, const PxVec3& position = PxVec3(0, 0, 0), const PxReal spacing = 0.2f, const PxReal totalClothMass = 10.0f) {
    PxCudaContextManager* cudaContextManager = gScene->getCudaContextManager();
    if (cudaContextManager == NULL) {
        std::cout << "No cuda manager." << std::endl;
    }

    const PxU32 numParticles = numX * numZ;
    const PxU32 numSprings   = (numX - 1) * (numZ - 1) * 4 + (numX - 1) + (numZ - 1);
    const PxU32 numTrianges  = (numX - 1) * (numZ - 1) * 2;

    const PxReal resetOffset      = spacing;
    const PxReal stretchStiffness = 10000.0f;
    const PxReal shearStiffness   = 100.0f;
    const PxReal springDamping    = 0.001f;

    // create PBDmaterial for cloth.
    PxPBDMaterial*       defaultMat     = gPhysics->createPBDMaterial(0.8f, 0.05f, 1e+6f, 0.001f, 0.5f, 0.005f, 0.05f, 0.0f, 0.0f);
    PxPBDParticleSystem* particleSystem = gPhysics->createPBDParticleSystem(*cudaContextManager);
    gParticleSystem                     = particleSystem;

    // set particle settings.
    const PxReal particleMass = totalClothMass / numParticles;
    particleSystem->setRestOffset(resetOffset);
    particleSystem->setContactOffset(resetOffset + 0.02f);
    particleSystem->setParticleContactOffset(resetOffset + 0.02f);
    particleSystem->setSolidRestOffset(resetOffset);
    particleSystem->setFluidRestOffset(0.0f);
    gScene->addActor(*particleSystem);

    PxU32                        particlePhase = gParticleSystem->createPhase(defaultMat, PxParticlePhaseFlags(PxParticlePhaseFlag::eParticlePhaseSelfCollideFilter | PxParticlePhaseFlag::eParticlePhaseSelfCollide));
    PxParticleClothBufferHelper* clothBuffers  = PxCreateParticleClothBufferHelper(1, numTrianges, numSprings, numParticles, cudaContextManager);

    PxU32*  phase           = cudaContextManager->allocPinnedHostBuffer<PxU32>(numParticles);
    PxVec4* positionInvMass = cudaContextManager->allocPinnedHostBuffer<PxVec4>(numParticles);
    PxVec4* velocity        = cudaContextManager->allocPinnedHostBuffer<PxVec4>(numParticles);

    PxReal x    = position.x;
    PxReal y    = position.y;
    PxReal z    = position.z;
    PxReal maxZ = z;

    // define springs and triangles.
    PxArray<PxParticleSpring> springs;   // springs.
    PxArray<PxU32>            triangels; // triangles vertexs.
    springs.reserve(numSprings);
    triangels.reserve(numTrianges * 3);

    // --j0,1,2------
    // i0------------
    // i1------------
    // i2------------
    for (PxU32 i = 0; i < numX; i++) {
        for (PxU32 j = 0; j < numZ; j++) {
            const PxU32 index = i * numZ + j;
            PxVec4      pos(x, y, z, 1.0f / particleMass); // x,y,z,invMass

            phase[index]           = particlePhase;
            velocity[index]        = PxVec4(0.0f);
            positionInvMass[index] = pos;

            // vertical
            if (i > 0) {
                PxParticleSpring spring = {id(i - 1, j, numZ), id(i, j, numZ), spacing, stretchStiffness, springDamping, 0};
                springs.pushBack(spring);
            }

            // horizontal
            if (j > 0) {
                PxParticleSpring spring = {id(i, j - 1, numZ), id(i, j, numZ), spacing, stretchStiffness, springDamping, 0};
                springs.pushBack(spring);
            }

            // duijiao
            if (i > 0 && j > 0) {
                PxParticleSpring spring0 = {id(i - 1, j - 1, numZ), id(i, j, numZ), PxSqrt(2.0f) * spacing, shearStiffness, springDamping, 0};
                PxParticleSpring spring1 = {id(i - 1, j, numZ), id(i, j - 1, numZ), PxSqrt(2.0f) * spacing, shearStiffness, springDamping, 0};
                springs.pushBack(spring0);
                springs.pushBack(spring1);

                // ============================================
                // (i-1,j-1)0---3(i-1,j)
                //          | / |
                // (i  ,j-1)1---2(i  ,j)
                // ============================================

                // triangle: [0, 3, 1]
                triangels.pushBack(id(i - 1, j - 1, numZ));
                triangels.pushBack(id(i - 1, j, numZ));
                triangels.pushBack(id(i, j - 1, numZ));

                // triangle: [3, 1, 2]
                triangels.pushBack(id(i - 1, j, numZ));
                triangels.pushBack(id(i, j - 1, numZ));
                triangels.pushBack(id(i, j, numZ));
            }
            z = z + spacing;
        }
        maxZ = z - spacing;
        z    = position.z;
        x    = x + spacing;
    }

    PX_ASSERT(numSprings == springs.size());
    PX_ASSERT(numTrianges == triangels.size() / 3);

    clothBuffers->addCloth(0.0f, 0.0f, 0.0f, triangels.begin(), numTrianges, springs.begin(), numSprings, positionInvMass, numParticles);

    ExtGpu::PxParticleBufferDesc bufferDesc;
    bufferDesc.maxParticles       = numParticles;
    bufferDesc.numActiveParticles = numParticles;
    bufferDesc.positions          = positionInvMass;
    bufferDesc.velocities         = velocity;
    bufferDesc.phases             = phase;

    const PxParticleClothDesc&   clothDesc         = clothBuffers->getParticleClothDesc();
    PxParticleClothPreProcessor* clothPreProcessor = PxCreateParticleClothPreProcessor(cudaContextManager);

    PxPartitionedParticleCloth output;
    clothPreProcessor->partitionSprings(clothDesc, output);
    clothPreProcessor->release();

    gClothBuffer = ExtGpu::PxCreateAndPopulateParticleClothBuffer(bufferDesc, clothDesc, output, cudaContextManager);
    gParticleSystem->addParticleBuffer(gClothBuffer);
    clothBuffers->release();

    cudaContextManager->freePinnedHostBuffer(positionInvMass);
    cudaContextManager->freePinnedHostBuffer(velocity);
    cudaContextManager->freePinnedHostBuffer(phase);
}

struct Triangle {
    PxU32 ind0;
    PxU32 ind1;
    PxU32 ind2;
};

PxTriangleMesh* initMesh() {
    const PxU32  gridSize     = 8;
    const PxReal groudSize    = 100.0f;
    const PxReal gridStep     = groudSize / (gridSize - 1);
    const PxU32  numTriangles = (gridSize - 1) * (gridSize - 1) * 2;

    PxVec3   verts[gridSize * gridSize];
    Triangle indices[numTriangles];
    for (PxU32 z = 0; z < gridSize; ++z) {     // z-axis
        for (PxU32 x = 0; x < gridSize; ++x) { // x-axis
            verts[z * gridSize + x] = PxVec3(-groudSize * 0.5f + x * gridStep, 0.0f, -groudSize * 0.5f + z * gridStep);
        }
    }

    for (PxU32 z = 0; z < (gridSize - 1); ++z) {
        for (PxU32 x = 0; x < (gridSize - 1); ++x) {
            Triangle& tri0 = indices[(z * (gridSize - 1) + x) * 2];
            Triangle& tri1 = indices[(z * (gridSize - 1) + x) * 2 + 1];

            // 0-----1
            // |  \  |
            // 3-----2
            // [0, 1, 2]
            tri0.ind0 = z * gridSize + x + 1;
            tri0.ind1 = z * gridSize + x;
            tri0.ind2 = (z + 1) * gridSize + x + 1;
            // [0, 2, 3]
            tri1.ind0 = (z + 1) * gridSize + x + 1;
            tri1.ind1 = z * gridSize + x;
            tri1.ind2 = (z + 1) * gridSize + x;
        }
    }

    PxTriangleMeshDesc meshDesc;
    meshDesc.points.data      = verts;
    meshDesc.points.count     = gridSize * gridSize;
    meshDesc.points.stride    = sizeof(PxVec3);
    meshDesc.triangles.data   = indices;
    meshDesc.triangles.count  = numTriangles;
    meshDesc.triangles.stride = sizeof(Triangle);

    PxCookingParams cookingParams(gPhysics->getTolerancesScale());
    PxTriangleMesh* mesh = PxCreateTriangleMesh(cookingParams, meshDesc, gPhysics->getPhysicsInsertionCallback());
    return mesh;
}

void initPhysics() {
    gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
    gPhysics    = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(), true); // no pvd
    gDispatcher = PxDefaultCpuDispatcherCreate(2);
    gMaterial   = gPhysics->createMaterial(0.5f, 0.5f, 0.6f);

    // cuda environment.
    PxCudaContextManager* cudaContextManager = NULL;
    if (PxGetSuggestedCudaDeviceOrdinal(gFoundation->getErrorCallback()) >= 0) {
        PxCudaContextManagerDesc cudaContextManagerDesc;
        cudaContextManager = PxCreateCudaContextManager(*gFoundation, cudaContextManagerDesc, PxGetProfilerCallback());
        if (cudaContextManager && !cudaContextManager->contextIsValid()) {
            cudaContextManager->release();
            cudaContextManager = NULL;
        }
    }
    if (cudaContextManager == NULL) {
        PxGetFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Failed to initialize CUD!\n");
    }

    // create scene description.
    PxSceneDesc sceneDesc(gPhysics->getTolerancesScale());
    sceneDesc.gravity            = PxVec3(0.0f, -9.8f, 0.0f);
    sceneDesc.cpuDispatcher      = gDispatcher;
    sceneDesc.filterShader       = PxDefaultSimulationFilterShader;
    sceneDesc.cudaContextManager = cudaContextManager;
    sceneDesc.staticStructure    = PxPruningStructureType::eDYNAMIC_AABB_TREE;
    sceneDesc.flags |= PxSceneFlag::eENABLE_PCM;
    sceneDesc.flags |= PxSceneFlag::eENABLE_GPU_DYNAMICS;
    sceneDesc.broadPhaseType = PxBroadPhaseType::eGPU;
    sceneDesc.solverType     = PxSolverType::eTGS;
    gScene                   = gPhysics->createScene(sceneDesc);

    // create background
    // PxRigidStatic* groundPlane = PxCreatePlane(*gPhysics, PxPlane(0, 1, 0, 0), *gMaterial);
    // gScene->addActor(*groundPlane);

    // create groundMesh
    PxTriangleMesh*        mesh = initMesh();
    PxTriangleMeshGeometry geom(mesh);
    PxRigidStatic*         groundMesh = gPhysics->createRigidStatic(PxTransform(PxVec3(0, -1, 0)));
    PxRigidActorExt::createExclusiveShape(*groundMesh, geom, *gMaterial);
    gScene->addActor(*groundMesh);

    // create rigid body.
    const PxReal size      = PxReal(0.5);
    const PxReal mass      = PxReal(1.0);
    PxShape*     box_shape = gPhysics->createShape(PxBoxGeometry(size, size, size), *gMaterial);
    for (size_t k = 0; k < 3; k++) {
        for (size_t j = 0; j < 3; j++) {
            for (size_t i = 0; i < 10; i++) {
                if (k == 1 & j == 1) {
                    continue;
                }
                PxTransform     localTm = PxTransform(PxVec3(3.0f * j, size * (2 * i + 1), 3.0f * k) - PxVec3(1, 0, 1));
                PxRigidDynamic* body    = gPhysics->createRigidDynamic(localTm);
                PxRigidBodyExt::updateMassAndInertia(*body, mass);
                body->attachShape(*box_shape);
                gScene->addActor(*body);
            }
        }
    }
    box_shape->release();

    // create shpere.
    const PxReal radius       = PxReal(1.0);
    PxShape*     sphere_shape = gPhysics->createShape(PxSphereGeometry(radius), *gMaterial);
    for (size_t i = 0; i < 30; i++) {
        PxTransform     localTm = PxTransform(PxVec3(0.0f, radius * (2 * i + 1) + 8, 0.0f) * radius);
        PxRigidDynamic* body    = gPhysics->createRigidDynamic(localTm);
        PxRigidBodyExt::updateMassAndInertia(*body, mass);
        body->attachShape(*sphere_shape);
        gScene->addActor(*body);
    }
    sphere_shape->release();

    // create cloth shape.
    const PxReal totalClothMass = 10.0f;
    PxU32        numX           = 250;
    PxU32        numZ           = 250;
    PxReal       spacing        = 0.06f;
    PxVec3       position       = PxVec3(-0.5f * numX * spacing, 8.0f, -0.5f * numZ * spacing);
    initCloth(numX, numZ, position, spacing, totalClothMass);
}

void allocParticleBuffers() {
    PxCudaContextManager* cudaContextManager = gScene->getCudaContextManager();
    PxU32                 maxParticles       = gClothBuffer->getMaxParticles();
    sPosBuffer.initialize(cudaContextManager);
    sPosBuffer.allocate(maxParticles * sizeof(PxVec4));
}

void renderLoop() {
    sCamera = new Snippets::Camera(PxVec3(10.0f, 10.0f, 10.0f), PxVec3(-0.6f, -0.2f, -0.7f));
    Snippets::setupDefault("SimpleDemo", sCamera, keyCallback, renderCallback, exitCallback);

    initPhysics();          // init all physics variables and environment.
    allocParticleBuffers(); // alloc memory for cloth render.
    glutMainLoop();         // enetr the render loop.
}

int snippetMain(int, const char* const*) {
    renderLoop(); // call the renderloop
    cleanupPhysics();
    return 0;
}

Thanks very much!

gjkPenetration() crash

I've run into a situation where gjkPenetration() (the function at line 98 of GuGJKPenetration.h) fails to calculate a proper penetration info for colliding convex hulls, which leads to an assert being thrown in debug mode (and later stack corruption due to out-of-bounds array access).

Unfortunately I don't really have a way of providing a snippet for the crashing setup, but the ultimately cause of the assert and fix are easy to understand:

On the 4th iteration of the loop at line 204, 'closest' is returning from 'GJKCPairDoSimplex' as a zero vector (0,0,0,0). That leads to 'v' turning into a NaN vector (-nan, -nan, -nan, -nan) due to the division by zero in the call to V3ScaleInv on line 265. The NaN vector prevents the loop from breaking, which means in future iterations where 'size' is >= 5 the assert on line 259 is triggered. And of course accessing the prior arrays with an index >= 5 causes some out-of-bounds stack corruption, leading to a crash.

I wasn't able to solve the zero vector mystery (improperly cooked convex hull? The cooking function itself returned 'success' on the geometry, but who knows)....but the fix is easy: by checking if 'closest' is a zero vector before the call to V3ScaleInv and returning 'GJK_DEGENERATE' if it is, the crash is averted....and in the simulation itself the failed penetration calculation for the problem contact doesn't seem to really have a visible effect on the result.

This is what I put on line 263 to solve the crashing issue:

if (FAllEq(closest, zeroV))
{
    return GJK_DEGENERATE;
}

Either way it would be nice to return cleanly from that function in the case of bad inputs, rather than crashing.

Werror flag is making impossible to compile in Linux (Manjaro)

Library and Version

4d33492

Operating System

Manjaro 22.0.2
gcc version 12.2.1 20230111 (GCC)

Steps to Trigger Behavior

  1. git clone https://github.com/NVIDIA-Omniverse/PhysX.git
  2. cd PhysX/physx
  3. generate_projects.sh
  4. cd compiler/linux-debug/ && make

Here is error message:

/physx/source/lowlevel/software/src/PxsCCD.cpp:1767:8: error: variable 'totalActivePairs' set but not used [-Werror,-Wunused-but-set-variable]
        PxU32 totalActivePairs = 0;

Code Snippet to Reproduce Behavior

<your-snippet>

Expected Behavior

Everything compiles

Actual Behavior

Warning became compile error - it does not compile

Fast fix

I fixed its by removing flag -Werror from file ./PhysX/physx/source/compiler/cmake/linux/CMakeLists.txt

external/cmakemodules is missing in PhysX 5

I am building physx from CMake (the .cmake in physx/compiler/public). The cmake file needs CMAKEMODULES_PATH which is used to be find in the Physx/externals/. After upgrading to PhysX 5, all the externals are removed. How should I build the project with cmake now

Unstable Behavior with TGS Solver and Non-Identity ChildFrame in Articulations with Limited Spherical Joints

Hello!

I am encountering unstable behaviors when utilizing articulations and spherical PxArticulationJoints . Specifically, the issue arises when the childFrame is set to a non-Identity value, and the joint is limited. Everything functions correctly when using the PGS solver. However, the TGS solver exhibits unexpected instability. Is this a known issue? Is there a workaround? or is it just a misconception on my part?

Library and Version

PhysX v5.1.3

Operating System

Linux

Steps to Trigger Behavior

  1. Create a Simple Articulated body with two links and a spherical joint.
  2. Set the child frame of the joint to a non-identity matrix.
  3. Set Limit Params for every axis of motion.
  4. Switch Between PGS and TGS Solver

Code Snippet to Reproduce Behavior

Articulation Create Code Snippet
static void createArticulation() {

    // Root Transformation Matrix
    PxMat44 restTf;
    restTf.column0 = PxVec4(0.9550508869395391, 0.2964415309802544f, -0.0004712388805974386f, 0.f);
    restTf.column1 = PxVec4(-0.29644151513976624f, 0.9550510023739125f, -0.00010471974330090952f, 0.f);
    restTf.column2 = PxVec4(0.00048110044630012515f, 0.f, 1.f, 0.f);
    restTf.column3 = PxVec4(3.f, 3.254410193471301f, 0.f, 1.f);

    // General Articulation Config
   //  gArticulation->setSolverIterationCounts(255U);
    gArticulation->setSolverIterationCounts(8, 1);
    gArticulation->setArticulationFlag(PxArticulationFlag::eFIX_BASE, true);
    gArticulation->setArticulationFlag(PxArticulationFlag::eDISABLE_SELF_COLLISION, true);


    // Root Link Shape, Material, and Properties
    PxMaterial* material = gPhysics->createMaterial(0.6f, 0.6f, 0.01f);
    PxShape* rootShape = gPhysics->createShape(PxCapsuleGeometry(1.f, 8.289946556091309 * 0.5f), *material);
    rootShape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, true);
    rootShape->setRestOffset(0.02f);

    PxTransform pxtm{PxVec3(4.144f, 0.f, 0.f)};
    rootShape->setLocalPose(pxtm);

    const auto tol = gPhysics->getTolerancesScale();
    rootShape->setContactOffset(0.02f * tol.length);

    // Add Root Link to Articulation
    PxArticulationLink* rootLink = gArticulation->createLink(NULL, PxTransform(PxTransform(restTf)));
    rootLink->attachShape(*rootShape);
    rootLink->setName("root");
    rootLink->setMaxContactImpulse(PX_MAX_F32);
    rootLink->setMaxDepenetrationVelocity(PX_MAX_F32);
    rootLink->setLinearDamping(0.5f);
    rootLink->setAngularDamping(1.f);
    PxRigidBodyExt::updateMassAndInertia(*rootLink, 30.f);

    // Link 1 Shape, Material, and Properties
    PxMaterial* material1 = gPhysics->createMaterial(0.6f, 0.6f, 0.01f);
    PxShape* link1Shape = gPhysics->createShape(PxCapsuleGeometry(1.f, 1.7120577096939087 * 0.5f), *material1);
    link1Shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, true);
    link1Shape->setRestOffset(0.02f);

    pxtm = PxTransform{PxVec3(0.8560288548469543f, 0.f, 0.f)};
    link1Shape->setLocalPose(pxtm);

    rootShape->setContactOffset(0.02f * tol.length);

    // Add Link 1 to Articulation
    PxArticulationLink* link1 = gArticulation->createLink(rootLink, PxTransform(PxIdentity));
    link1->attachShape(*link1Shape);
    link1->setName("link1");
    link1->setMaxContactImpulse(PX_MAX_F32);
    link1->setMaxDepenetrationVelocity(PX_MAX_F32);
    link1->setLinearDamping(0.5f);
    link1->setAngularDamping(1.f);
    PxRigidBodyExt::updateMassAndInertia(*link1, 2.1980769634246826f);

    // Add joint between root and link 1
    PxArticulationJointReducedCoordinate* joint1 = link1->getInboundJoint();

    // Spherical joint
    joint1->setJointType(PxArticulationJointType::eSPHERICAL);

    // Define parent (from root to joint) and child frames (from link1 to joint) for joint
    PxMat44 parentFrame;
    parentFrame.column0 = PxVec4(0.201f, -0.980f, 0.f, 0.f);
    parentFrame.column1 = PxVec4(0.980f, 0.201f, 0.f, 0.f);
    parentFrame.column2 = PxVec4(0.f, 0.f, 1.f, 0.f);
    parentFrame.column3 = PxVec4(8.289946135028046f, 0.f, 0.f, 1.f);
    joint1->setParentPose(PxTransform(parentFrame));

    PxMat44 childFrame;
    childFrame.column0 = PxVec4(-1.0f, 0., 0.f, 0.f);
    childFrame.column1 = PxVec4(0.0f, -1.0f, 0.f, 0.f);
    childFrame.column2 = PxVec4(0.f, 0.f, 1.f, 0.f);
    childFrame.column3 = PxVec4(0.f, 0, 0.f, 1.f);
    joint1->setChildPose(PxTransform(childFrame));

    // We want joint to be limited
    joint1->setMotion(PxArticulationAxis::eTWIST, PxArticulationMotion::eLIMITED);
    joint1->setMotion(PxArticulationAxis::eSWING1, PxArticulationMotion::eLIMITED);
    joint1->setMotion(PxArticulationAxis::eSWING2, PxArticulationMotion::eLIMITED);

    // 30 deg -> 0.523599 rad
    PxArticulationLimit pxlimit(-0.523599, 0.523599);
    joint1->setLimitParams(PxArticulationAxis::eTWIST, pxlimit);

    // 45 deg -> 0.785398 rad
    pxlimit = PxArticulationLimit(-0.785398, 0.785398);
    joint1->setLimitParams(PxArticulationAxis::eSWING1, pxlimit);

    // 37.223 deg -> 0.65 rad
    pxlimit = PxArticulationLimit(-0.65, 0.65);
    joint1->setLimitParams(PxArticulationAxis::eSWING2, pxlimit);

    // Add Articulation to Scene
    gScene->addArticulation(*gArticulation);

    // SetGlobalPose instead of using cache to keep code as short as possible
    gArticulation->setRootGlobalPose(PxTransform(restTf));
    gArticulation->updateKinematic(PxArticulationKinematicFlag::ePOSITION);
}
Init Physics Code Snippet
void initPhysics(bool /*interactive*/) {
    gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
    gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale());

    PxSceneDesc sceneDesc(gPhysics->getTolerancesScale());
    sceneDesc.gravity = PxVec3(0.0f, -9.81f, 0.0f);

    // // TGS Causes unstable behavior
    sceneDesc.solverType = PxSolverType::eTGS;
    // sceneDesc.solverType = PxSolverType::ePGS;
    sceneDesc.filterShader = PxDefaultSimulationFilterShader;

    PxU32 numCores = SnippetUtils::getNbPhysicalCores();
    gDispatcher = PxDefaultCpuDispatcherCreate(numCores == 0 ? 0 : numCores - 1);
    sceneDesc.cpuDispatcher = gDispatcher;
    gScene = gPhysics->createScene(sceneDesc);

    // Add a ground plane
    gMaterial = gPhysics->createMaterial(0.5f, 0.5f, 0.f);
    PxRigidStatic* groundPlane = PxCreatePlane(*gPhysics, PxPlane(0, 1, 0, 0), *gMaterial);
    gScene->addActor(*groundPlane);

    gArticulation = gPhysics->createArticulationReducedCoordinate();
    createArticulation();
}
Step Physics Code Snippet
void stepPhysics(bool /*interactive*/) {
    // Small dt, want to match my use case, tried larger dt as well but error persits
    const PxReal dt = 0.0052;

    gScene->simulate(dt);
    gScene->fetchResults(true);
}
int main() {
    // using render Loop from articulationrc snippet
    extern void renderLoop();
    renderLoop();
    return 0;
}

Expected Behavior

The articulation with the spherical joint should exhibit stable and accurate behaviors, regardless of the childFrame configuration. Both the TGS solver and the PGS solver should yield consistent results.

Actual Behavior

TGS

tgs.mp4

PGS

pgs.mp4

Thank you in advance!

Spring/damper doing nothing for articulations

When trying to drive my articulation joints, only "max_force" affects my articulation moving speed. Spring/damper can be zero or a billion, it makes no difference. What could be wrong? Physx 5.1.3..(used from rust but that shouldn't matter)

pub fn set_articulation_joint_reduced_target(
    joint: PtrArticulationJointReducedCoordinate,
    axis: PxArticulationAxis,
    max_force: f32,
    spring: f32,
    damper: f32,
    target: f32,
) {
    unsafe {
        let drive = PS::PxArticulationDrive_new_1(
            spring,
            damper,
            max_force,
            PS::PxArticulationDriveType::Target,
        );

        PS::PxArticulationJointReducedCoordinate_setDriveParams_mut(joint, axis, &drive);
        PS::PxArticulationJointReducedCoordinate_setDriveTarget_mut(joint, axis, target, true);
        }
}

Any chance we'll get more snippets?

Hi there, I just integrated PhysX 5 into my engine, for basic shapes, after having previously integrated Jolt (which was fine, but PVD and Omniverse and backing from Nvidia + use in most games convinced me to restart).

I was wondering if you'll be adding more snippets, especially for the Character Controller aspect. I know there is a doc page about it but it would save me time / effort if there were something similar to Jolt's sample, where you can walk around and jump on moving objects, etc. Jolt's been out for far longer but so far seems to have way more developed test gyms. Reference implementation and samples are so important, so I hope you can do us all a solid and add more snippets, especially a character controller gym. This is the bread and butter of gaming so it would be great to see, in practice, how you would implement these things. Including a jump button, character being pushed (or not) by objects. I worry that Jolt simply has better functionality in this respect, but I just couldn't risk using a physics engine that's only maintained by 1 person as a hobby / side project. But still, Jolt so far has much better code samples and I hope this is one area that PhysX will continue to improve upon.

Thanks.

Cloth simulation settings

Thanks for this great work!
The cloth in snippetPBDCloth somehow seems to be too extensible (like jelly? or thin rubber? I think real cloth is way more 'rigid'?๏ผ‰
What can I do to make it look like real cloth (like a coat)? (I read the api document and wiki, but I still don't know how to correct it. :<)

Undefined Symbols during runtime

Hi there,

I'm trying to use the PhysX API within a ROS2 node. I've cloned this repository and followed the build instructions. I'm using Ubuntu 20.04 LTS and have built the "checked" version of PhysX. All the snippets run without any issues.

The instructions for building applications with PhysX refer to adding the /include and /bin folder to the project's makefile but since ROS2 auto generates the makefiles I have to do it at the package's CMakeLists.txt level. Hence I've added the following to my CMakeLists.txt:

include_directories($ENV{PHYSX_INCLUDE})
include_directories($ENV{PHYSX_BIN})

target_link_libraries(vehicle_simulator_node
    ${PROJECT_NAME}
    $ENV{PHYSX_LIB}/libPhysXCharacterKinematic_static_64.a
    $ENV{PHYSX_LIB}/libPhysXCommon_static_64.a
    $ENV{PHYSX_LIB}/libPhysXCooking_static_64.a
    $ENV{PHYSX_LIB}/libPhysXExtensions_static_64.a
    $ENV{PHYSX_LIB}/libPhysXFoundation_static_64.a
    $ENV{PHYSX_LIB}/libPhysXGpu_64.so
    $ENV{PHYSX_LIB}/libPhysXPvdSDK_static_64.a
    $ENV{PHYSX_LIB}/libPhysX_static_64.a
    $ENV{PHYSX_LIB}/libPhysXVehicle2_static_64.a
    $ENV{PHYSX_LIB}/libPhysXVehicle_static_64.a
    $ENV{PHYSX_LIB}/libPVDRuntime_64.so
)

Here is the output of env:

PHYSX_ROOT=/home/ubuntu/PhysX
PHYSX_BIN=/home/ubuntu/PhysX/physx/bin
PHYSX_LIB=/home/ubuntuPhysX/physx/bin/linux.clang/checked
PHYSX_INCLUDE=/home/ubuntu/PhysX/physx/include

I've also added the following lines to my application's header file where I'd be initialising PhysX:

#define NDEBUG
#include "PxPhysicsAPI.h"

Within this file I have the following lines for initialising PhysX:

static PxDefaultErrorCallback gDefaultErrorCallback;
static PxDefaultAllocator gDefaultAllocatorCallback;
PxFoundation *mFoundation;
PxPhysics *mPhysics;

And when I run my ROS2 node I get the following error:

undefined symbol: _ZN319VehicleSimulator16VehicleSimulator21gDefaultErrorCallbackE, at /tmp/binarydeb/ros-foxy-rcutils-1.1.4/src/shared_library.c:84

If I instead make the DefaultAllocator and ErrorCallabck non static like so:

PxDefaultErrorCallback gDefaultErrorCallback;
PxDefaultAllocator gDefaultAllocatorCallback;

I get a different undefined symbol error:

undefined symbol: _ZN5physx2Gu24intersectBoxVsMesh_RTREEERKNS0_3BoxERKNS0_12TriangleMeshERKNS_12PxTransformTIfEERKNS_11PxMeshScaleEPNS0_14LimitedResultsE, at /tmp/binarydeb/ros-foxy-rcutils-1.1.4/src/shared_library.c:84

This suggests that there was an issue with properly linking the PhysX libraries, but I'm not sure what I've done wrong. Any help would be much appreciated. Please let me know if you need any more details. Thanks.

Contact target velocity not zeroed out?

It appears that calling setTargetVelocity() on a contact point can affect other contact points in subsequent time-steps. Perhaps the contact velocity is not zeroed out every time-step. This only appears to happen when using the CPU dispatcher rather than the GPU/CUDA dispatcher.

PhysX_Contact_Velocity_Issue

Expected Behavior

The boxes below the conveyor resting on the floor should not move regardless of whether a box is moving on the conveyor.

Actual Behavior

Some of the boxes below the conveyor move when a box is moving on the conveyor.

Library and Version

PhysX v5.1.3

Operating System

Windows 11

Steps to Trigger Behavior

Run code snippet provided and press space to create a box.

Code Snippet to Reproduce Behavior

The snippet provided below is a simple modification of the SnippetHelloWorld.cpp which reproduces the behavior.

#include <ctype.h>
#include "PxPhysicsAPI.h"
#include "../snippetcommon/SnippetPrint.h"
#include "../snippetcommon/SnippetPVD.h"
#include "../snippetutils/SnippetUtils.h"

using namespace physx;

static PxDefaultAllocator		gAllocator;
static PxDefaultErrorCallback	gErrorCallback;
static PxFoundation*			gFoundation = NULL;
static PxPhysics*				gPhysics	= NULL;
static PxDefaultCpuDispatcher*	gDispatcher = NULL;
static PxScene*					gScene		= NULL;
static PxMaterial*				gMaterial	= NULL;
static PxPvd*					gPvd        = NULL;

float conveyorSpeed = 0.5F;
PxRigidDynamic* conveyor = nullptr;

class ContactModifyCallback : public PxContactModifyCallback
{
public:
	void onContactModify(PxContactModifyPair* const pairs, PxU32 count)
	{
		for (PxU32 i = 0; i < count; ++i)
		{
			PxContactModifyPair& pair = pairs[i];

			// Conveyor.
			if (pair.actor[0] == conveyor || pair.actor[1] == conveyor)
			{
				for (PxU32 j = 0; j < pair.contacts.size(); ++j)
				{
					pair.contacts.setStaticFriction(j, 0.35F);
					pair.contacts.setDynamicFriction(j, 0.35F);
					pair.contacts.setNormal(j, PxVec3(0.0, 1.0, 0.0));
					pair.contacts.setTargetVelocity(j, PxVec3((pair.actor[0] == conveyor) ? conveyorSpeed : -conveyorSpeed, 0.0, 0.0));
				}
			}
			else
			{
				for (PxU32 j = 0; j < pair.contacts.size(); ++j)
				{
					pair.contacts.setStaticFriction(j, 0.35F);
					pair.contacts.setDynamicFriction(j, 0.35F);
					//pair.contacts.setTargetVelocity(j, PxVec3(0.0));
				}
			}
		}
	}
};

static PxFilterFlags ContactReportFilterShader(PxFilterObjectAttributes attributes0, PxFilterData filterData0,
	PxFilterObjectAttributes attributes1, PxFilterData filterData1,
	PxPairFlags& pairFlags, const void* constantBlock, PxU32 constantBlockSize)
{
	PX_UNUSED(attributes0);
	PX_UNUSED(attributes1);
	PX_UNUSED(filterData0);
	PX_UNUSED(filterData1);
	PX_UNUSED(constantBlockSize);
	PX_UNUSED(constantBlock);

	pairFlags = PxPairFlag::eDETECT_DISCRETE_CONTACT | PxPairFlag::eMODIFY_CONTACTS | PxPairFlag::eSOLVE_CONTACT;
	return PxFilterFlag::eDEFAULT;
}

static PxRigidDynamic* createBox(const PxVec3& position, const PxVec3& dimensions)
{
	PxTransform transform(position, PxQuat(PxIdentity));
	PxBoxGeometry geometry(dimensions * 0.5F);
	PxRigidDynamic* dynamic = PxCreateDynamic(*gPhysics, transform, geometry, *gMaterial, 10.0f);
	gScene->addActor(*dynamic);
	return dynamic;
}

static PxRigidDynamic* createLoad(const PxVec3& position, const PxVec3& dimensions)
{
	PxRigidDynamic* load = createBox(position, dimensions);
	load->setSolverIterationCounts(8, 2);
	load->setSleepThreshold(0.0);
	PxRigidBodyExt::setMassAndUpdateInertia(*load, 1.0);
	return load;
}

void initPhysics(bool interactive)
{
	PX_UNUSED(interactive);

	gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);

	gPvd = PxCreatePvd(*gFoundation);
	PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate(PVD_HOST, 5425, 10);
	gPvd->connect(*transport,PxPvdInstrumentationFlag::eALL);

	gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(),true,gPvd);

	PxSceneDesc sceneDesc(gPhysics->getTolerancesScale());
	sceneDesc.cudaContextManager = nullptr;
	gDispatcher = PxDefaultCpuDispatcherCreate(2);
	sceneDesc.cpuDispatcher = gDispatcher;
	sceneDesc.filterShader = PxDefaultSimulationFilterShader;
	sceneDesc.solverType = PxSolverType::ePGS;
	sceneDesc.filterShader = ContactReportFilterShader;
	sceneDesc.flags |= PxSceneFlag::eENABLE_GPU_DYNAMICS;
	sceneDesc.flags |= PxSceneFlag::eENABLE_PCM;
	sceneDesc.flags |= PxSceneFlag::eENABLE_FRICTION_EVERY_ITERATION;
	sceneDesc.broadPhaseType = PxBroadPhaseType::eABP;
	sceneDesc.contactModifyCallback = new ContactModifyCallback();
	sceneDesc.gravity = PxVec3(0.0f, -9.81f, 0.0f);
	
	gScene = gPhysics->createScene(sceneDesc);

	PxPvdSceneClient* pvdClient = gScene->getScenePvdClient();
	if(pvdClient)
	{
		pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, true);
		pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONTACTS, true);
		pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES, true);
	}
	gMaterial = gPhysics->createMaterial(0.0F, 0.0F, 0.0F);
	gMaterial->setFlags(PxMaterialFlag::eIMPROVED_PATCH_FRICTION);

	PxRigidStatic* groundPlane = PxCreatePlane(*gPhysics, PxPlane(0,1,0,0), *gMaterial);
	gScene->addActor(*groundPlane);

	conveyor = createBox(PxVec3(0.0, 1.0, 0.0), PxVec3(2.0, 0.1, 0.3));
	conveyor->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true);

	createLoad(PxVec3(-0.4, 0.05, 0.0), PxVec3(0.1, 0.1, 0.1));
	createLoad(PxVec3(-0.2, 0.05, 0.0), PxVec3(0.1, 0.1, 0.1));
	createLoad(PxVec3(0.0, 0.05, 0.0), PxVec3(0.1, 0.1, 0.1));
	createLoad(PxVec3(0.2, 0.05, 0.0), PxVec3(0.1, 0.1, 0.1));
	createLoad(PxVec3(0.4, 0.05, 0.0), PxVec3(0.1, 0.1, 0.1));
}

void stepPhysics(bool /*interactive*/)
{
	gScene->simulate(1.0f/100.0f);
	gScene->fetchResults(true);
}
	
void cleanupPhysics(bool /*interactive*/)
{
	PX_RELEASE(gScene);
	PX_RELEASE(gDispatcher);
	PX_RELEASE(gPhysics);
	if(gPvd)
	{
		PxPvdTransport* transport = gPvd->getTransport();
		gPvd->release();	gPvd = NULL;
		PX_RELEASE(transport);
	}
	PX_RELEASE(gFoundation);
	
	printf("SnippetHelloWorld done.\n");
}

void keyPress(unsigned char key, const PxTransform& camera)
{
	PX_UNUSED(camera);

	switch(toupper(key))
	{
	case ' ':	createLoad(PxVec3(0.4, 1.3, 0.0), PxVec3(0.3, 0.2, 0.2));	break;
	}
}

int snippetMain(int, const char*const*)
{
#ifdef RENDER_SNIPPET
	extern void renderLoop();
	renderLoop();
#else
	static const PxU32 frameCount = 100;
	initPhysics(false);
	for(PxU32 i=0; i<frameCount; i++)
		stepPhysics(false);
	cleanupPhysics(false);
#endif

	return 0;
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.