nvidia-omniverse / physx Goto Github PK
View Code? Open in Web Editor NEWNVIDIA PhysX SDK
License: BSD 3-Clause "New" or "Revised" License
NVIDIA PhysX SDK
License: BSD 3-Clause "New" or "Revised" License
5.1.3
aarch64-apple-darwin
aarch64-apple-darwin
Irrelevant
PhysX compiles
PhysX fails to compile for several reasons:
<xmmintrin.h>
if PX_OSX
is 1, which fails since that is an x86 only header. See EmbarkStudios@1e04de1 for a commit to fix thisUnknown 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
But it appears like iOS support has been completely dropped in PhysX 5 (with no CHANGELOG entry) resulting in these errors.
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.
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.
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...
<your-snippet>
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.
vs
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.
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);
}
}
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
Manjaro 22.0.2
gcc version 12.2.1 20230111 (GCC)
git clone https://github.com/NVIDIA-Omniverse/PhysX.git
cd PhysX/physx
generate_projects.sh
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;
<your-snippet>
Everything compiles
Warning became compile error - it does not compile
I fixed its by removing flag -Werror
from file ./PhysX/physx/source/compiler/cmake/linux/CMakeLists.txt
PhysX v5.1.0
Manjaro Linux
PhysX/physx/include
/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
Fine Compilation
Error message
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
Hello,
I'm always happy for proprietary tech to become fully FLOSS but some people noticed a potential conflict between:
Could you clarify?
% 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".
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?
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.
The boxes below the conveyor resting on the floor should not move regardless of whether a box is moving on the conveyor.
Some of the boxes below the conveyor move when a box is moving on the conveyor.
PhysX v5.1.3
Windows 11
Run code snippet provided and press space to create a box.
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;
}
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.
Release 104.0.
Any.
$ bash generate_projects.sh linux
Build script connects to bootstrap.packman.nvidia.com over TLS.
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.
PhysX v5.1.0
Linux
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;
}
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
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
release/104.2
Windows 10
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.
(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)
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
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.
PhysX v5.1.0
Windows 10 / Windows 11
In Sc::Scene::postIslandGen
, mSetEdgesConnectedTask and mNPhaseCore->processTriggerInteractions can be called in concurrent tasks,
PhysX/physx/source/simulationcontroller/src/ScScene.cpp
Lines 3695 to 3704 in 93b6c25
mSetEdgesConnectedTask will call Sc::Scene::setEdgesConnected
wich in turn call wakeObjectsUp
PhysX/physx/source/simulationcontroller/src/ScScene.cpp
Lines 3458 to 3475 in 93b6c25
wakeObjectsUp
may activate actors and their Interactions, wich will end up calling Sc::Scene::notifyInteractionActivated
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)
mNPhaseCore->processTriggerInteractions calls NPhaseCore::mergeProcessedTriggerInteractions
wich will call Sc::Scene::notifyInteractionDeactivated
PhysX/physx/source/simulationcontroller/src/ScNPhaseCore.cpp
Lines 1632 to 1647 in 93b6c25
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();
}
A similar issue is located in Sc::Scene::processLostContacts2
, Sc::Scene::lostTouchReports
and Sc::Scene::unregisterInteractions
will be called concurrently,
PhysX/physx/source/simulationcontroller/src/ScScene.cpp
Lines 3948 to 3955 in 93b6c25
Sc::Scene::lostTouchReports
will wake actors on lost touch, wich will end up calling Sc::Scene::notifyInteractionActivated
PhysX/physx/source/simulationcontroller/src/ScScene.cpp
Lines 3870 to 3894 in 93b6c25
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)
Sc::Scene::unregisterInteractions
will call Sc::Scene::unregisterInteraction
.
PhysX/physx/source/simulationcontroller/src/ScScene.cpp
Lines 3896 to 3919 in 93b6c25
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 :
PhysX/physx/source/simulationcontroller/src/ScScene.cpp
Lines 3948 to 3955 in 93b6c25
After :
void Sc::Scene::processLostContacts2(PxBaseTask* continuation)
{
mDestroyManagersTask.setContinuation(continuation);
mLostTouchReportsTask.setContinuation( &mDestroyManagersTask );
mUnregisterInteractionsTask.setContinuation( &mLostTouchReportsTask );
mUnregisterInteractionsTask.removeReference();
mLostTouchReportsTask.removeReference();
PhysX v5.1.0 (release/104.0)
PhysX
target using clang 14 - compilation succeedsPhysX
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)
cmake --build . --target PhysX
g++11 should successfully compile the PhysX
target
g++11 is not able to compile the PhysX
target
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.
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?
PhysX v5.1.3
Linux
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);
}
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();
}
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;
}
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.
TGS
PGS
Thank you in advance!
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).
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
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
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.
PhysX v5.1.0
Release 104.0
Hi,
There is a precision issue in the computation of the vertex index in Gu::HeightField::computeCellCoordinates.
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.
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.
found the issue
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
PhysX v5.1.3
Windows 11
No code required.
To be able to put this on a users machine, inside a folder which contains a space, and that it works.
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.
PhysX ToT (main branch)
macOS 22.1.0 ARM
#! /bin/bash
./generate_projects.sh
cd _compiler/gmake2
make config=debug_x86_64
make config=release_x86_64
cd ../..
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).
./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.
You are missing the option to create vc17win64 with CMAKE.
Example: PhysX v5.1.2
Windows 10
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)
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);
Body is not moving and rotating or body is moving and rotating
Body is moving but not rotating.
In code block
PhysX/physx/source/lowleveldynamics/src/DyRigidBodyToSolverBody.cpp
Lines 75 to 80 in 93b6c25
lin
variable instead of data.linearVelocity
.Version : 5.1.3.32494398
Windows 10
I am trying to build physx with Cmake.
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)
Error:
"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]
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.
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.
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:
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.
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.
I want to Use Blast With PhysX5 and find that it still refer to PhysX4.1.
Is there anyway possible that I can use Blast with PhysX5 ?
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:
PhysX 5.1.0
Linux
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]);
}
I would expect the velocity of the second link to be some non-zero value if the first joint is moving at 1m/s
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
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 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!
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. :<)
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.
PhysX v5.1.2
Example: Windows 10 20H2
PxQueryFilterCallback::postFilter(const PxFilterData& filterData, const PxQueryHit& hit, const PxShape* shape, const PxRigidActor* actor)
, return PxQueryHitType::eNONE
for unexpected actors.xQueryFlag::ePOSTFILTER
PxSceneQueryExt::overlapMultiple(*m_pScene, geometry, pose, hitBuffer, bufferSize, filterData, filterCall);
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);
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.
overlapMultiple()
still return 1, even the postFilter()
return PxQueryHitType::eNONE
.
SnippetRender::renderSoftBodyGeometry
only render three faces for each tetrahedron as tetFaces
uses incorrect vertice indexs.
should be
const int tetFaces[4][3] = { {0,2,1}, {0,1,3}, {0,3,2}, {1,2,3} };
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.
PhysX v5.1.2
PhysX v5.1.3
Windows 10
Windows 11
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
It seems like suspDirVelWheel
should be used in line 373.
PhysX/physx/source/physxvehicle2/src/suspension/VhSuspensionFunctions.cpp
Lines 365 to 376 in 4d33492
-gravitySuspDir * dt * dt > previousJounce + jounceSpeed * dt
. It is possible case when vehicle is flipped.
PhysX v5.1.2
Window 10
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.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.