Showing posts with label PhysX. Show all posts
Showing posts with label PhysX. Show all posts

Friday, 11 July 2014

PhysX - Distance Joint

Introduction to Joint Springs

Just like Fixed Jointswe need a couple rigid actors.
    PxRigidActor* pRA1,* pRA2;

I'll give them box shapes of unit length.
    PxBoxGeometry geo(PxVec3(0.5,0.5,0.5));

    PxTransform pform = PxTransform::createIdentity();

In our example one will be kinematic, to hold up the other.
    pform.p = PxVec3(0,5,0);
    pRA1 = PxCreateDynamic(*gPhysicsSDK, pform,geo,*defaultMaterial, 1.0);
    pRA1->isRigidDynamic()->setRigidDynamicFlag(PxRigidDynamicFlag::eKINEMATIC,true);

    pform.p = PxVec3(2,5,2);
    pRA2 = PxCreateDynamic(*gPhysicsSDK, pform,geo,*defaultMaterial, 1.0);
 
Add them to the scene.
    gScene->addActor(*pRA1);
    gScene->addActor(*pRA2);

We will also need a couple transforms to represent the where the joint attaches to the two actors.
    PxTransform local1 = PxTransform::createIdentity(), local2= PxTransform::createIdentity();

Creating the joint is done as before.
    PxDistanceJoint* pJoint = PxDistanceJointCreate(*gPhysicsSDK, pRA1, local1 ,pRA2, local2);

and although not necessary this time we can set the collision flag.
    pJoint->setConstraintFlag(PxConstraintFlag::eCOLLISION_ENABLED,true);

The distance joint may act as a string or a spring, connecting the two actors. There are three flags available for the distance joint.

    PxDistanceJointFlag::
        eSPRING_ENABLED
        eMAX_DISTANCE_ENABLED
        eMIN_DISTANCE_ENABLED

by default only the eMAX_DISTANCE_ENABLED is active. With the spring flag disabled the max distance is a hard limit for the joint. However if the spring flag is enabled then this becomes the distance at which the spring force becomes active.



Similarly a minimum distance can be set, but cannot exceed the maximum distance, the spring force will pull the actors to remain between the min and max distance limits.

Recall the Force equation for a spring:

    F_spring = - k * x

where 'k' is the spring constant, and 'x' is the distance from the natural length, or in our case, the distance from the min or max limits.

The force experienced by the actors will need to be adjusted by a damping force

    F_damping = - c * x'

where 'c' is the damping coefficient, and x' is the first derivative with respect to time of the distance from the natural length (the speed)

    F_net = F_spring + F_damping - F_gravity

A spring experiencing a damping force will eventually stop at an equilibrium length (not necessarily the same as the natural length)

The magnitude of the damping coefficient should be chosen to fall into one of four categories. These categories are decided by the ability of the damping to stop the oscillation.

let z = c/sqrt(4mk);

  • Un-Damped ( z == 0, so c must be 0)
    Choose Un-Damped if you want the spring to oscillate back and forth forever.
  • Under-Damped ( 0 < z < 1)
    Choose under damped if you want some resemblance of a spring effect where it may oscillate back and forth a few times before coming to rest at an equilibrium state. 
  • Critically-Damped ( z ==1 )
    Choose critically damped if you want the spring to slow perfectly to it's equilibrium.
  • Over-Damped ( z > 1 )
    Choose over damped if you want the spring to slow down a lot to start and very gradually approach equilibrium. 



From left to right we have No Spring, Un-damped, Under-damped, Critically-damped, and Over-damped. The distance joint without a spring stops immediately at its maximum distance. For the rest, the spring does not begin applying a tension until they pass that maximum distance.

Notice that although critically-damped, the box overshoots it's equilibrium position anyway. This is because of the extra momentum generated before the spring was active. I will explain this further in a future post.

Setting the values are straight forward,

    pJoint->setSpring(15.0f);
  pJoint->setMaxDistance(3.0f);
    pJoint->setMinDistance(1.0f);
    pJoint->setDamping(0.5);

but are meaningless without the corresponding flag set.

    pJoint->setDistanceJointFlag(PxDistanceJointFlag::eSPRING_ENABLED,true);


Hopefully this gives an preview of how distance joints are created and how the spring feature works.
Happy Coding!


Thursday, 3 July 2014

Getting Started : PhysX - Fixed Joints

Introduction to PhysX Joints

PhysX provides a number of options for the types of joints which may be created. I will work through the creation of each pointing out aspects which might be of interest.

The basic formula for creating any joint is the same. We need access to the PxPhysics singleton factory, at least one rigid actor, and the transform from each actor to the point where the joint is formed.

    Px[Type]Joint* Px[Type]JointCreate(
        PxPhysics& physics,
        PxRigidActor* actor0, const PxTransform& localFrame0,
        PxRigidActor* actor1, const PxTransform& localFrame1);

As mentioned, only one of the two actors needs to be defined. It is possible to create a joint by attaching one side to a point in world space (in which case a NULL pointer may be passed for the actor).

Fixed Joint

Arguably the simplest case, and perhaps the most unused, a fixed joint provides no freedom of movement. It's most useful feature is that it can be broken while experiencing an applied force. After creating a fixed joint I explain how to choose appropriate values for the break force and torque.

First we need our shapes and actors, we can start with some boxes of unit size.

    PxBoxGeometry boxGeo(PxVec3(0.5,0.5,0.5)); //Dimensions are for half-length

    PxRigidActor *pRA1, *pRA2;
    PxTransform kform = PxTransform::createIdentity();

    kform.p = PxVec3(0,3,0);
    pRA1 = PxCreateDynamic(*gPhysicsSDK, kform ,boxGeo,*defaultMaterial, 1.0);
    pRA1->isRigidDynamic()->setRigidDynamicFlag(PxRigidDynamicFlag::eKINEMATIC,true);

    kform.p = PxVec3(1,3,0);
    pRA2 = PxCreateDynamic(*gPhysicsSDK, kform , boxGeo,*defaultMaterial, 1.0);

I have set one of the actors to be kinematic so it will remain suspended despite gravity, while the other will be held up entirely by the strength of the joint. Since the boxes they are of unit length, and are one unit apart, the surfaces will be in contact.

It should also be noted that the joint is formed between the two actors and not the shapes themselves. If the shape isn't centered on the actor, or the actor contained multiple shapes then we might want to consider different local frames.

    PxTransform local1 = PxTransform::createIdentity(),
        local2= PxTransform::createIdentity();

    local1.p = PxVec3(0.5,0,0);
    local2.p = PxVec3(-0.5,0,0);

    PxFixedJoint* pJoint = PxFixedJointCreate(*gPhysicsSDK, pRA1, local1 ,pRA2, local2);

I have moved the position of the local frame to be the same distance as the half-length of the box. This way the joint exists at the edge of the box and not within it. Leaving the position at (0,0,0) will center the joint on the middle of the actor causing the two actors to draw together until they overlap. Moving the local frame further from the origin will force the actors to start further apart. I have made it so that the joint end positions fall exactly on the surface of the box.

For a fixed joint there are two important modifiers to consider. First is the break force, which defines the force and the torque at which the joint will break. These are set to a maximum value by default, but there are some cases in which you would want actors to break apart.

    pJoint->setBreakForce(fForce, fTorque);

In this example the weight of the actor is a force of its own which could break the joint. A box of unit size, and of unit density will have a unit mass.

    mass = 1.0f;

and if we set gravity to a convenient number,

    gravity = PxVec3(0.0f, -10.0f, 0.0);

then the shearing force on our arrangement is

    Force = mass*gravity = 1.0 * -10.0 = -10.0

so in order for one box to not break the joint we need a minimum break force of 10.0.

We also need to consider the torque of the actors themselves. In the simple case like this, where the applied force (due to the weight of the object) is already perpendicular to the axis of the joint the torque calculation is simple.

    Torque = length x force = |length|*|force|*sin(90deg) = |length|*|force|

the length of the lever arm is measured from the joint to the actor, which is also the magnitude of the position vector of the local frame.

    length = |localPose2.p| = |(-0.5,0,0)| = 0.5

    Torque = length * force = 0.5 * 10.0 = 5.0

These are example calculations of the minimum force and torque required to suspend a box of unit size and density off the side of a fixed actor. Further estimations should be made to accommodate for collisions with other actors as well.



The other important modifier is the constraint flag. In particular the default setting is that objects constrained by a joint are allowed to pass through each other. The only constraint is the one enforced by the joint itself. In some cases it may be better for actors connected by a joint to be allowed to interact and collide with each other.

    pJoint->setConstraintFlag(PxConstraintFlag::eCOLLISION_ENABLED, true);

Best of luck finding uses for fixed joints.
Happy Coding!

Wednesday, 13 November 2013

PhysX with 64-bit using VS2008

This seems to be an important feature for some to have, so I wanted to see how difficult it would be to compile and run under a 64-bit architecture. At least for NVIDIA's PhysX (both 2.8.x, and 3.2.x) it was really really easy.

Recall we needed a few dll's, which are a direct swap for the ones already copied into the project folder. 

//PhysX 2.8.4
   cudart64_30_9.dll
   PhysXCore64.dll
   PhysXLoader64.dll

//PhysX 3.2.1
   PhysX3_64.dll
   PhysXCommon_x64.dll

Of course if you have a more advanced application you may also need other libraries, but for the most basicc rigid body simulation these are essential and demonstrate the pattern for the other libraries. If you are missing any of these dll's, then it may tell you when you run the debugger (PhysX 3.2.1), or you will likely get a Null return from 
NxCreatePhysicsSDK with error code NXCE_PHYSX_NOT_FOUND.

If you use premake like me to generate Visual Studio solutions then you need to indicate these changes as well in the .lua files and specify the target platform in the .bat file. Snippets of mine looks like this :

//HelloWorld-Premake.lua

   local physXSDK = 'C:/Program Files (x86)/NVIDIA Corporation/NVIDIA PhysX SDK/v3.2.1_win'

   includedirs { physXSDK .. '/Include/foundation' }
   includedirs { physXSDK .. '/Include' }
   includedirs { physXSDK .. '/Include/common' }
   includedirs { physXSDK .. '/Include/extensions' }

   links { physXSDK .. '/lib/win64/PhysX3_x64' }
   links { physXSDK .. '/lib/win64/PhysX3Extensions' }
   links { physXSDK .. '/lib/win64/PhysX3Common_x64' }
   links { physXSDK .. '/lib/win64/PhysXVisualDebugger' }

//CreateSolutions.bat

   ..\..\premake\Premake4 --file=HelloWorld-Premake.lua --platform=x64 vs2008

If you didn't do a complete install the first time, visual studio 2008 does not come with the x64 compiler by default and you will have to re-install, adding the x64 as a custom feature. This may prompt for the location of other files, I found this solution helpful.

*Remember that you will also need to get the correct rendering libraries, or else the program will build, but fail to execute properly. See Error : "The application was unable to start correctly (0xc000007b)".*

If there is more work to be done for custom allocators, I will update this posting to include those changes as well. Until then, Happy Coding!


Saturday, 13 July 2013

Getting Started : PhysX

I've using one of the most popular physics game engines, Nvidia PhysX, and it also appears to be one of the most popular, as reported by physxinfo. The versions I'm reasonably familiar with are the v2.8 and v3.2, but I will only discuss the use of v3.2 for now. When I was getting started myself, I found this other blog very helpful for both.


My goal is to show how to create a simple 2-body system - a bouncing box. As much as possible, the steps for other physics engines will remain the same. So moving between engines should look very similar. In the end this is what I would consider to be the essential steps for setting up any physics engine, so there may not be much information about the various settings available.

0) Setting up the environment

If you're using Visual Studio it may be helpful to use Premake as I've described previously. In any case, you'll need to provide the appropriate paths to some include directories as well as the full path to required library files.

Here I have already defined physXSDK to point to the v3.2.1_win folder and will have the following.
--Directories to Include
    physXSDK .. '/Include'
    physXSDK .. '/Include/common' 
    physXSDK .. '/Include/extensions'
    physXSDK .. '/Include/foundation'

--Libraries to Link
    physXSDK .. '/lib/win32/PhysX3_x86'
    physXSDK .. '/lib/win32/PhysX3Common_x86'
    physXSDK .. '/lib/win32/PhysX3Extensions'

Also, in the project configuration settings, be sure to set the correct platform defines. Or else you risk having run-time issues at initialization because of the wrong alignment.

    defines{ "WIN32" }


1) Including the Headers

To keep things simple you can include the two following header files.

    #include <PxPhysicsAPI.h>
    #include <PxExtensionsAPI.h>

You will see that they contain includes to nearly all the classes you'll need. The alternative it to include just the files you need, in which case PxPhysicsAPI could be replaced with four others.

    #include <PxPhysics.h>
    #include <PxScene.h>
    #include <PxRigidDynamic.h>
    #include <PxRigidStatic.h>

We need PxPhysics for initializing the SDK, PxScene for the world in which we will add both Rigid Dynamic and Rigid Static actors into. In exactly this way will we setup our methods, but before we begin we will also need the physx namespace, a change effective in the 3.x versions of PhysX.

2) Adding the namespace

    using namespace physx;

3) Initialization

There should only be one instance of the sdk created so I have chosen to make a static global variable.

    static PxPhysics* sgpPhysicsSDK = NULL;

In order to satisfy the PxPhysics constructor, we will need a few things. First we will need to also create the 'Foundation'. This requires an implementation of both an allocator and an error callback class. Thankfully there is a default implementation for both that we can use for now.

    PxFoundation* pkFoundation = PxCreateFoundation( PX_PHYSICS_VERSION, 
        *(new PxDefaultAllocator()), *(new PxDefaultErrorCallback()));

    sgpPhysicsSDK = PxCreatePhysics(PX_PHYSICS_VERSION, *pFoundation, PxTolerancesScale());

4) Creating the Scene

As with the initialization I will use the default implementations wherever required and only use the provided validity checks.

//Similar to the 2.8 version of PhysX, the PxScene is created

//by first filling the scene descriptor.
    PxSceneDesc kSceneDesc(sgpPhysicsSDK->getTolerancesScale());

//gravity is set to 0 by default.
    kSceneDesc.gravity = PxVec3(0.0f, -9.8f, 0.0f);

//This is for the number of threads it will have access to.
    PxDefaultCpuDispatcher* pkCpuDispatcher =     PxDefaultCpuDispatcherCreate(1);
    if(kCpuDispatcher)
        kSceneDesc.cpuDispatcher = pkCpuDispatcher;
    PxSimulationFilterShader kDefaultFilterShader =     PxDefaultSimulationFilterShader;
    kSceneDesc.filterShader = kDefaultFilterShader;
    if(kSceneDesc.isValid())
        sgScene = sgPhysicsSDK->createScene(kSceneDesc);



Finally, we can add the actor to the scene.

Nearly all shapes can be removed from actors, with a few exceptions. When releasing actors, all remaining shapes will be removed. We can then remove the actors from the scene, and scenes from the SDK. 



5) Creating Actors

Another important change from PhysX 2.8.x is that actor creation is now controlled by the SDK manager, PxPhysics, and not by the scene. This means that actors can be created and exist separate from the world, and can be added or removed without repeatedly destroying and recreating them later. Shapes, however, go with the actor and cannot be so seamlessly removed and re-added like the actors' relationship to the scene.

Things you will need: A material, appropriate geometry, mass/density, and a pose for the shape. You will also need a pose for the actor.
    PxReal kDensity = 1.0f;

    PxMaterial* pMaterial = sgpPhysicsSDK->createMaterial(0.0,0.0,1);

//Material is the static friction, dynamic friction, and restitution respectively.
    PxBoxGeometry kBoxGeometry;
    kBoxGeometry.halfExtents = PxVec3(0.5f,0.5f,0.5f);
    PxTransform kLocalPose = PxTransform::createIdentity();

    PxVec3 kPosition(0,0,5.0f);

    PxQuat kOrientation = PxQuat::createIdentity();
    PxTransform kGlobalPose(kPosition, kOrientation);

There are two ways to go about creating Actors and Shapes, it all depends on how much information you have.

A - There are static calls you can make, which are especially good if you have all the information and only intend to add one shape to the actor.

    PxRigidDynamic* pDynamicActor = PxCreateDynamic(sgpPhysicsSDK, kGlobalPose, kBoxGeometry,
        *pMaterial, kDensity, kLocalPose);

B - The alternative is to create the unfilled actor from the SDK, and add all this same information in a series of steps.

    PxRigidDynamic* pDynamicActor = sgPhysicsSDK->createRigidDynamic(kGlobalPose);
    pDynamicActor->createShape(kBoxGeometry, *pMaterial, kLocalPose);
    PxRigidBodyExt::updateMassAndInertia(pDynamicActor, kDensity);

In either case, if you continue to add shapes to the actor, then you should call updateMassAndInertia with a list of densities for each shape flagged for simulation, PxShapeFlag::eSIMULATION_SHAPE

    sgScene->addActor(*pDynamicActor);

6) Simulation

The simulation step is straight forward. We can pick a reasonable time step, or a division of our predicted timestep and call simulate and fetchResults one after another.

    PxReal fTimestep 1.0/60.0f;
    PxU32 uiErrorState = 0;
    bool bBlock = true;

    sgScene->simulate(fTimestep);
    sgScene->fetchResults(bBlock, &uiErrorState);

In some examples Nvidia separates the simulate and fetch into pre and post rendering steps, but it would seem fine to perform rending after calling a simulate/fetch pair. The blocking parameter in fetchResults is typically set to true, otherwise fetchResults may return false because the results are not yet ready. It is acceptable to call fetchResults multiple times in this case. Which you could write as:

    sgScene->simulate(fTimestep);
    while(!sgScene->fetchResults(false, &uiErrorState){}

This gives control to the user to do something else useful in the meantime. Similarly the timestep can be subdivided and the pairing called multiple times, which may be necessary for stability or synchronization.

7) Shutdown/Cleanup

    PxU32 uiActorCount = sgScene->getNbActors(     PxActorTypeSelectionFlag::eRIGID_STATIC | PxActorTypeSelectionFlag::eRIGID_DYNAMIC);
    PxActor** pActorBuffer = (PxActor**)malloc(uiActorCount*sizeof(PxActor*));
    for(PxU32 ui =0; ui<uiActorCount; ui++)
    {
        sgScene->removeActor(*pActorBuffer[ui]);
        pActorBuffer[ui]->release();
    }
    sgpPhysicsSDK->release();
//all instances of the sdk need to be released before the next two
    delete sgpDefaultErrorCallback;
    delete sgpDefaultAllocatorCallback;

This should be good enough to get started. I'll try to cover other rigid-body topics like joints at a later time. 
Happy Coding.