PhysX 3.3.1 Integration Notebook

Changelog

July 29, 2014 Updated Rigid Body Section
July 24, 2014 Added Rigid Body Physics
July 9, 2014 Added details on collision spheres
July 2, 2014 Added more cloth tearing info and cloth scale section.
June 29, 2014 First entry

Dear Zach, In case of time machine, read this before you start implementing the PhysX SDK. Sincerely, Zach

Getting Error Messages & Feedback

There are 2 things that would have saved me a few weeks of work had I enabled them from the start.

PhysX Visual Debugger

PhysX Visual Debugger (PVD) is #1. It’s dead simple to get setup following the Nvidia example and it provides you invaluable feedback. Mostly its value is to make sure that what you think is happening is actually what’s happening. Look at the physics objects in PVD alongside with your game, compare the cloth particle count and placement in your game engine along with the PVD, they should sync up.

PhysX Visual Debugger

Run the Checked Build

You should always run the checked build. If you’re working with PhysX in a plugin system, you’ll need to attach the debugger to your main process. Doing so will let you see the assert messages that pop up in the Visual Studio console. They will tell you when you do stupid things, like pass bogus (but not invalid) parameters to class instantiations. You might otherwise spend a lot of time figuring out why your physics objects are acting oddly.

Cloth

PxClothMeshDesc Weights

Of course you understand that these weights determine whether the cloth particle is simulated or static. 0 means the particle is static, > 0 means that the particle is simulated. Usually, we just use 0.0f and 1.0f to distinguish these two. A key part of setting up the cloth correctly is making lists of the vertices that need to be frozen in place vs simulated.  You’ll need to write a few custom tools that allow you to select these vertices and save them out as a list so that you can populate these weights at runtime. Don’t bother trying to split up your vertices and cloth weights into separate variables. I originally tried stuffing the weights into their own array and would continuously get the error:

..\..\PhysX\src\NpFactory.cpp (427) : invalid parameter : PxPhysics::createCloth: particle values must be finite and inverse weight must not be negative

Despite the fact that my particle values were finite in length/value and all my inverse weights were non-zero. Eventually I gave up and followed the nvidia sample code where they stuff the vertices and weights into a single PxVec4 like a thanksgiving day turkey. Vertices go in (x,y,z) and weight goes in (w).

Cloth Is Tearing

You may get excited that you’ve found a new feature to allow tearing of cloth when half your flag just up and jumps off the flagpole. If your cloth is falling apart like this. It probably means that your mesh has duplicate vertices. In my case, the tessellated plane had duplicate vertices that needed to be welded.

Cloth Tearing

There is at least 1 other case that causes tearing. The problem is that not all duplicate vertices are geometric. In my case, some duplicate vertices in other meshes were part of the UV map. If any of these vertices are set to simulated, the cloth will have issues. Since I wasn’t able to separate out the UV from the mesh vertices, I wrote a quick check for duplicate vertices and made sure that they were forced to a weight of 0.0f.

Red vertices are duplicates

Cloth Scale

The scale of the cloth can be tricky. When you are slurping down the vertice translations info for PxClothMeshDesc, you need to multiply each vertice by the relevant scale factor of the object so that the space representation in PhysX is the same as in the engine. The problem comes in during the update phase when you’re matching the vertices in engine with the vertices as PhysX delivers them. I soon discovered that after updating the vertices in engine, the engine was applying the original scale factor to them! This results in a double scaling.

It’s pretty obvious what’s going on here. The coordinates in the engine are local space and get a scale factor applied. One option is to apply a reverse scale factor in the vertice update function. This has a huge downside in that to do this you have to transform every individual vertice each frame. In my case, I’m using a single function call to update my mesh vertices which has speed advantages. So, the simple solution is to:

  1. Create PxClothMeshDesc with scaled vertices
  2. Set the object uniform scale to 1

This workaround gives PhysX the correctly scaled vertices and then relies on the PhysX representation for future updates. Since the uniform scale is then essentially zero’d out (at 1), no further scale factor is applied to mesh vertice updates!

Cloth Collision Spheres

Collision sphere positions are defined in the Local Space of the cloth object! When defining the collision spheres that make up each capsule for a character, it made more sense to define those in terms of local space offsets from each bone. Then once you know the offset from the character root to the cloth root, you can apply the necessary transforms to update the sphere positions each frame.

Collision sphere's are defined in local space of the cloth root.

A small sidenote here is that using a boxy model with spherical colliders does not look very accurate when simulated.

Rigid Body Physics

Filter Shader for Rigid Static Collision

When using a custom filter shader, filter masks seem to be completely ignored on rigid static objects. I’ve asked why. Here is my current filter shader that handles rigid static collisions correctly.

PxFilterFlags MyFilterShader(PxFilterObjectAttributes attributes0, PxFilterData filterData0, 
                            PxFilterObjectAttributes attributes1, PxFilterData filterData1,
                            PxPairFlags& pairFlags, const void* constantBlock, PxU32 constantBlockSize)
{
    // let triggers through
    if(PxFilterObjectIsTrigger(attributes0) || PxFilterObjectIsTrigger(attributes1))
    {
        pairFlags = PxPairFlag::eTRIGGER_DEFAULT;
        return PxFilterFlag::eDEFAULT;
    }

    // generate contacts for all that were not filtered above
    pairFlags = PxPairFlag::eCONTACT_DEFAULT;

    // Check for static object collision
    if( PxGetFilterObjectType(attributes0) == PxFilterObjectType::eRIGID_STATIC || PxGetFilterObjectType(attributes1) == PxFilterObjectType::eRIGID_STATIC )
    {
        pairFlags |= PxPairFlag::eNOTIFY_TOUCH_FOUND | PxPairFlag::eNOTIFY_CONTACT_POINTS ;
        return PxFilterFlags();
    }

    // trigger the contact callback for pairs (A,B) where
    // the filtermask of A contains the ID of B and vice versa.
    if((filterData0.word0 & filterData1.word1) && (filterData1.word0 & filterData0.word1))
    {
        pairFlags |= PxPairFlag::eNOTIFY_TOUCH_FOUND | PxPairFlag::eNOTIFY_CONTACT_POINTS ;
        return PxFilterFlags();
    }

    // If the mask didn't match, then suppress the collision
    return PxFilterFlag::eSUPPRESS;
}

Reducing Simulation Jitter

I found sub-stepping to greatly reduce jitter in my simulations involving kinematic actors.

Sub-Stepping

int substeps = 3; // Modify number of substeps based on your needs
float subStepSize = mStepSize / substeps;
for ( PxU32 subStepI = 0; subStepI  substeps; subStepI++ )
{
    gScene-simulate(subStepSize);
    gScene-fetchResults(true);
}

Also, thanks to Gordon at Nvidia, I discovered that I was not setting the moment of inertia on my actors. This was the main factor causing jitter and is also very noticeable because it causes objects to have very high moments of inertia which means it takes far less torque to get them spinning.

Be the first to comment

Leave a Reply