onShapeHit never gets called

Hi,

I was implementing CharacterControllers into my engine and came across an odd problem:
My Controllers wont collide with static geometry and even though I set a callback onShapeHit never gets called. When running my sample with PVD attached it looks like all the shapes are there but even when they start to overlap onShapeHit isn’t called.
Furthermore the character tosses dynamic actors around.
So to me it seems the character controller behaves strictly like a dynamic kinematic actor (which it is under the hood).
I have the eSCENE_QUERY_SHAPE and eSIMULATION_SHAPE set for all shapes and use the move() method of the character controller, which i thought would call onShapeHit.

This is my code for creating the CharacterController, I couldn’t spot any differences to the sample code shipped with the PhysX sdk.

PxCapsuleControllerDesc sDesc;
    sDesc.position = PxExtendedVec3( position.GetX(), position.GetY(), position.GetZ() );
    sDesc.userData = pElement;

    sDesc.radius = radius;
    sDesc.height = height;
    sDesc.slopeLimit = slopeLimit;
    sDesc.contactOffset = 0.1f;
    sDesc.stepOffset = 0.02f;
    sDesc.callback = this;
    sDesc.behaviorCallback = this;

    sDesc.material = pMaterial;

    if (sDesc.isValid())
        (*out_Character) = m_CharacterManager->createController( *m_pPhysX, scene.m_pScene, sDesc );
    else
        ReportPhysXError( GetName( ), "CreateCapsuleCharacter", "CharacterDescription invalid", ILoggingService::Error );

    PxRigidDynamic* pActor = (*out_Character)->getActor( );
    if ( pActor )
    {
        if ( pActor->getNbShapes( ) )
        {
            PxShape* ctrlShape;
            pActor->getShapes( &ctrlShape, 1 );

            if ( ctrlShape )
            {
                ctrlShape->setFlag( PxShapeFlag::eSCENE_QUERY_SHAPE, false );
            }
        }
    }

This is how i call move

PxControllerFilters filter = PxControllerFilters( );

    PxU32 collisionFlags = m_pController->move( CBVECTOR3D_2_PXVEC3( direction ), 0.001f, m_dt, filter );

    if ( PxControllerFlag::eCOLLISION_DOWN == collisionFlags )
    {
        // do something
    }

I used PVD to inspect my scene and the sample scene. There were no differences in the actors and shapes attributes.

Is there any flag I could habe possibly disabled that breaks the functionality of move()? I can’t shake the feeling that is something really minor I am missing here.

Thanks in advance for any help

Edit: attached a PVD scene with my scene. It has a Static and a Dynamic Actor and the Character Controller.
CharacterCtrl.zip (325 KB)

Hi,

please write which version of PhysX do you use.
I guess PhysX 3.2.x

One other thing: I think its not recommended to inheriate your “player” class the PxSimulationEventCallback - use a new class for it.
[If you have many “players” with different behaviour as example, its easier to modify it]

I didnt saw the PVD, but are your dynamic objects collideds with the trimesh?

Did you use a custom filtershader?
(Is m_dt a small value - (how fast are your player moving [gravity])

(Maybe your Trimesh face order is wrong)

Maybe the PhysXGuide or the Samples / Snipptes could help you.
Especially the Sample: Bridges / Character.
Please look inside it!

Do you get any Debug messages?

Yes its 3.2.x.
Yes I use a custom filter and it gets called when a dynamic actor overlaps with my controller but not when a static overlaps with it.

All other dynamics interact correctly with the heightfield. They also get tossed around by the character controller.

I checked the sampled but I still don’t see what I am missing.

Hi,

please post your custom filter.
There is a sample which shows a PxController walking on a heightfield - I guess
your filter is wrong.

Hi,

I don’t think the filter is the problem. I looked into the Northpole sample, which has a character walking on a heightfield and colliding with a static triangle mesh. The filter in this sample is not called when the character collides with statics. Only collisions with dynamics trigger the filter. Statics trigger onShapeHit (although not in my case).

Anyways this is my filter

static PxFilterFlags testCCDFilterShader(
    PxFilterObjectAttributes attributes0,
    PxFilterData filterData0,
    PxFilterObjectAttributes attributes1,
    PxFilterData filterData1,
    PxPairFlags& pairFlags,
    const void* constantBlock,
    PxU32 constantBlockSize )
{
    if ( filterData0.word3 & filterData1.word3 )
    {
        pairFlags |= PxPairFlag::eRESOLVE_CONTACTS;
        pairFlags |= PxPairFlag::eSWEPT_INTEGRATION_LINEAR;
    }

    return PxFilterFlag::eDEFAULT;
}

Hi,

Sorry I dont use PhysX 3.2x anymore, I´m using PhysX 3.3.
If I remember corretly, you have to set the ControllerCallback from the controllerManager pointer.

This changed in PhysX 3.3 - to a better system, each controller have to set a individual callback.
This is what im doing in 3.3:

mControllerDesc.reportCallback = reinterpret_cast<PxUserControllerHitReport*(…);

Your filtershader seems ok.

Maybe you have to set some values in the sceneDesc while creating Physics.

Why dont you change your project to PhysX 3.3 ? (release version of course)

Hi,

okay updating to 3.3 seems like a good idea :)
I did build a debug version of the PhysX3CharacterKinematicCHECKED_x86.dll and when going through the whole move method it seems like my shapes don’t get enumerated by the scenequery.
I saw that the scene query flag for statics is set and all my shapes have eSCENE_QUERY_SHAPE set to true.

Hi,

PhysX 3.3 fixed many bugs from 3.2.x and its faster than the older versions.

I just wondering why you wrote:

ctrlShape->setFlag( PxShapeFlag::eSCENE_QUERY_SHAPE, false );

  • It disables the Overlap / Raycast test for this shape.

Maybe you did something inside the creation of the PxHeighfield wrong - maybe you could post the creation of it.

Thats a little bit strange - does the samples work corretly for you?
Do you mix a /MTd build with /MDd build dont you?

Is there any warnings or other messages?

The sample works fine.

ctrlShape->setFlag( PxShapeFlag::eSCENE_QUERY_SHAPE, false );

Disdable the Character shape is recommended in the doumantation, but even turning it on again doesn’t solve my problem.

I’ll look into scene queries maybe I can find the root of the problem there.

I moved from a heightfield to a static box actor just to test it. Same result.

Hi,

maybe you forgot to create the PxScene with the flags: ( If needed )

sceneDesc.flags |= PxSceneFlag::eENABLE_KINEMATIC_STATIC_PAIRS | PxSceneFlag::eENABLE_KINEMATIC_PAIRS;

[PxController is kinematic, your static geometry is, of course static]

I dont need these flags, it works perfectly.
Or maybe your callback have a typo or something else was wrong written.

Did you already changed to PhysX 3.3?

Its better to post some code snippets where the problem could be - and to answer all of my hints :)

Okay now I am sure what the problem is. For some reason my shapes won’t show up in scene queries.
Is there any other setting besides eSCENE_QUERY_SHAPE (which is turned on) the needs to be enabled for scene queries to work?

Hi,

again, it would be much easier if you answer all my questions / show some code.

And please try what I wrote.

Hi,

finally I found the root of my problem.
Its the client ID. I created my scene with a client ID and set all my actors to use this ID.
But it looks like this breaks scene queries, I guess its a bug?
When I change my ID back to PX_DEFAULT_CLIENT everything works fine.

I am with similar problem.

When I use this code there is colision with terrain:

unsigned auxflags = controller->move(Convert::toPx(motion), minMoveDistance, dt, physx::PxControllerFilters(0));

When I use this code there is not collision with terrain:

const physx::PxControllerFilters filters(mFilterData);
unsigned auxflags = controller->move(Convert::toPx(motion), minMoveDistance, dt, filters);

mFilterData receives the same filter data from shape’s controller. But in this case, I don’t use filter callback for test and anyway there is not collision.

My filterData is:

word0 = groupReportCollision;
word1 = groupsMaskReportCollision; //with which groups will report collision
word2 = layerGroup

a found the same bug in topic: https://devtalk.nvidia.com/default/topic/609618/?comment=3947185

My problem is that I only was using the function:

pxShape->setSimulationFilterData(filterData);

Now, I set to all other shapes the QueryFilterData:

pxShape->setSimulationFilterData(filterData);
pxShape->setQueryFilterData(filterData);