NVIDIAGameWorks / PhysX

NVIDIA PhysX SDK
Other
3.19k stars 809 forks source link

Dynamic bodies mass not calculated properly with updateMassAndInertia? #642

Closed lpares12 closed 1 year ago

lpares12 commented 1 year ago

Hi, it seems like the gravity might be ignoring the mass of the dynamic bodies I'm creating.

First of all I initialize PhysX, create a scene, and check the gravity in it:

px_scene = px_physics->createScene(sceneDesc);
PxVec3 gravity = px_scene->getGravity(); // This returns (0, -9.81, 0);

And then I create two dynamic bodies with two shapes, calculate their mass and attach them to the scene:

PxGeometryHolder geometry_holder = PxBoxGeometry(PxVec3(1, 1, 1));
PxGeometryHolder geometry_holder2 = PxBoxGeometry(PxVec3(2, 2, 2));
PxMaterial px_material = px_physics->createMaterial(0.5, 0.5, 0.5);

px_shape1 = px_physics->createShape(geometry_holder.any(), &px_material, 1, false, flags);
px_shape2 = px_physics->createShape(geometry_holder2.any(), &px_material, 1, false, flags);

PxReal densities[5];
densities[0] = 1;

PxReal densities2[5];
densities2[0] = 1000;

px_actor1 = px_physics->createRigidDynamic(PxTransform(PxIdentity));
px_actor1->setGlobalPose(transform) // Sets position to (0, 10, 0)
px_actor1->attachShape(*px_shape1);
PxRigidBodyExt::updateMassAndInertia(*px_actor1, &densities[0], 1);

px_actor2 = px_physics->createRigidDynamic(PxTransform(PxIdentity));
px_actor2->setGlobalPose(transform) // Sets position to (0, 10, 5)
px_actor2->attachShape(*px_shape2);
PxRigidBodyExt::updateMassAndInertia(*px_actor2, &densities2[0], 1);
px_actor2->getMass(); // Returns 1000, but I think it should be 2000 since the volume of the shape is 2x2x2m

And when stepping through the simulation, both bodies fall down at the same velocity, which should not be the case.

If the shape 2 has size of 2x2x2m and a density of 1000, the mass of the px_actor2 should be 2000, but the getMass call for that shape is returning 1000.

So I see two problems in my script:

  1. The bodies with different volumes are falling at the same velocity (both with gravity enabled). Maybe that's expected because there's no friction with the "air"?
  2. UpdateMassAndInertia is not updating the mass according to the bodies.

In the docs I can't find any setting that I need to enable to make this work, is there something else I'm missing?

preist-nvidia commented 1 year ago

Hi @lpares12,

  1. Your hunch here is correct, the velocities, or better the acceleration will be identical for both objects despite their mass. Only with air-drag or other effects will you get differing speeds. This is my favorite video showcasing this fact: https://youtu.be/E43-CfukEgs?t=162
  2. Two things, I think you have a typo in the px_shape2 create, not using the geometry_holder2; second the box geometry constructor takes a vector describing the half-lengths of the cube, so the 1, 1, 1 cube is actually 2x2x2. https://nvidia-omniverse.github.io/PhysX/physx/5.1.3/_build/physx/latest/class_px_box_geometry.html?highlight=pxboxgeometry#_CPPv413PxBoxGeometry
lpares12 commented 1 year ago

Hi, thanks for the quick reply!

As for (2), yes, actually this is just a copy-paste of my bigger project, so might be I made a typo (due to the copy paste). And you are right, I actually divide/2 the size. But in any case, the density is not being computed correctly, seems to not take the volume of the shape into account. Even fixing the typo and so on, I can see the same behavior.

Let's say I set one box shape half-size to: (0.5, 0.5, 0.5) (meaning its volume will be 1m3) and a density of 1000. It means the shape should have a mass of 1000, correct? But then if I set another box to (1, 1, 1) (meaning its volume will be 8m3 and a density of 1000 it should have a mass of 8000, correct? But when I do so, it still says the mass is 1000, instead of 8000.

lpares12 commented 1 year ago

I wonder if I'm updating the shapes sizes correctly. Would it be enough to do:

PxGeometryHolder new_geometry = PxBoxGeometry(PxVec3(4, 4, 4));
px_shape->setGeometry(new_geometry.any());

// Recompute mass
PxRigidBodyExt::updateMassAndInertia(*px_actor1, &densities[0], 1);

This I'd expect to update the mass of the first actor to 512 assuming a density of 1.

preist-nvidia commented 1 year ago

@lpares12 The issue is that your shapes are shared and not exclusive. In that case you are not allowed to update them. It is a good idea to run in debug or checked configs, which will print issues.

preist-nvidia commented 1 year ago

I.e. you should see something like this:

C:\p\physx\PhysXSDK\trunk\source\physx\src\NpShape.cpp (272) : invalid parameter : PxShape::setGeometry: shared shapes attached to actors are not writable.
lpares12 commented 1 year ago

Thank you, this was the issue. I did see the logs, but seeing how the shape position and sizes and everything were correctly modified I still expected it to be okay.

Thanks again and sorry for opening a non-issue!

preist-nvidia commented 1 year ago

Yay! Glad it's resolved.