Is physics really difficult in UE4, or is it just me?

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);