NVIDIAGameWorks / PhysX

NVIDIA PhysX SDK
Other
3.18k stars 807 forks source link

Moving Articulations between scenes #333

Open zemlifr opened 4 years ago

zemlifr commented 4 years ago

Hello, is somehow possible to move existing ReducedCoordinateArticulation from one scene to another? Once I remove it fom scene and then add it again, i get CTD, because joint motion matrix is zeroed.

kstorey-nvidia commented 4 years ago

That sounds like a bug. The issue is that there's some dependent data that is computed and stored in the scene-allocated sim object, that is only recomputed if the corresponding dirty flags are set on the links/joints. In this case, the dirty flag will have been cleared when the articulation was simulated in the previous scene and have not been raised again when the articulation was inserted into the scene.

Can you try working around it by looping over all joints and calling something like setMotion with the exising values retrieved by calling getMotion() when you are attempting to add the articulation into the new scene? It's not ideal but setting the motion before insertion would mark those properties as dirty and could temporarily work around this issue by raising the dirty flag on the joints.

I will file a bug and aim to get a fix into the next version of PhysX.

zemlifr commented 4 years ago

@kstorey-nvidia Thank you for your quick reply.

Proposed solution didn't work, but it pointed me in right direction. I had to reset pose and drive to get all ArticulationJointCoreDirtyFlag invalidated.

joint->setChildPose(joint->getChildPose()); for (int i = 0; i < PxArticulationAxis::eCOUNT; i++) { const auto axis = static_cast(i); joint->setDriveTarget(axis, joint->getDriveTarget(axis)); joint->setDriveVelocity(axis, joint->getDriveVelocity(axis)); joint->setMotion(axis, joint->getMotion(axis)); }

Unfortunately, its still not ideal - Once re-inserted to scene, articulation is in default pose and then does quick move to get into drive target poses, which looks dumb.

Could PxArticulationCache be used to store state when articulation is removed from scene and then restore it once re-inserted?

zemlifr commented 4 years ago

I also forgot to say, I am using PhysX 4.0 (in case it is resolved in newer version)

joint->setMotion(axis, joint->getMotion(axis)); changes cache version so i had to omit that, but otherwise it works ok now. So result for anyone interested:

joint->setChildPose(joint->getChildPose()); for (int i = 0; i < PxArticulationAxis::eCOUNT; i++) { const auto axis = static_castPxArticulationAxis::Enum(i); joint->setDriveTarget(axis, joint->getDriveTarget(axis)); joint->setDriveVelocity(axis, joint->getDriveVelocity(axis)); } ..... _articulation->applyCache(*_cache, PxArticulationCache::eALL);