Ok, Here’s how I set the Center of Mass based on a socket on my StaticMesh, as well as set the Mass itself correctly:
FBodyInstance* BodyInst = StaticMeshComponent->GetBodyInstance();
if (!BodyInst) { return; }
BodyInst->bOverrideMass = true;
BodyInst->MassInKg = Mass;
BodyInst->UpdateMassProperties();
PxRigidBody* PRigidBody = BodyInst->GetPxRigidBody();
if (!PRigidBody) { return; }
FVector CenterOfMass = StaticMeshComponent->GetSocketLocation(FName("CenterOfMass"));
PxVec3 PWorldCOM;
PWorldCOM.x = CenterOfMass.X;
PWorldCOM.y = CenterOfMass.Y;
PWorldCOM.z = CenterOfMass.Z;
SCOPED_SCENE_READ_LOCK(PRigidBody->getScene());
PxVec3 PLocalCOM = PRigidBody->getGlobalPose().transformInv(PWorldCOM);
PRigidBody->setMass(Mass);
PxTransform trans;
trans.p = PLocalCOM;
PRigidBody->setCMassLocalPose(trans);
And here’s how I keep the center of mass and the moment of inertia constant after welding (not that I weld anymore, boo!!):
// What follows is a hack to prevent the attached component altering the existing physics
FBodyInstance* BodyInst = StaticMeshComponent->GetBodyInstance();
if (!BodyInst) { return; }
PxRigidBody* PRigidBody = BodyInst->GetPxRigidBody();
if (!PRigidBody) { return; }
PxTransform CenterOfMass = PRigidBody->getCMassLocalPose();
PxVec3 InertiaTensor = PRigidBody->getMassSpaceInertiaTensor();
// -- end hack
// Attach things here
// Now restore the previous settings
PRigidBody->setCMassLocalPose(CenterOfMass);
PRigidBody->setMassSpaceInertiaTensor(InertiaTensor);
You will need to include these:
#include "PhysXIncludes.h"
#include "PhysicsPublic.h"
#include "Runtime/Engine/Private/PhysicsEngine/PhysXSupport.h"
And you need to add some dependencies in your build file - PhysX and Apex which is just a single line in the file. There is a tutorial (as always) on the topic on the wiki.
As I said though, I found trying to weld bodies together a complete dead end, even with these hacks. Instead I just use a physics constraint component now instead and everything works as advertised.
UPDATE: I was running into some odd bugs with that code. Here’s what I now use to set the Center of mass:
FVector CenterOfMass = StaticMeshComponent->GetSocketLocation(FName("CenterOfMass"));
PxVec3 PWorldCOM(CenterOfMass.X, CenterOfMass.Y, CenterOfMass.Z);
PxScene* Scene = PRigidBody->getScene();
SCENE_LOCK_READ(Scene);
PxVec3 PLocalCOM = PRigidBody->getGlobalPose().transformInv(PWorldCOM);
SCENE_UNLOCK_READ(Scene);
SCENE_LOCK_WRITE(Scene);
PRigidBody->setMass(Mass);
PxTransform trans(PLocalCOM);
PRigidBody->setCMassLocalPose(trans);
SCENE_UNLOCK_WRITE(Scene);